Skip to main content

How to fix Error: Type is part of the declarations of 2 modules

If you encounter the issue, highly likely it means that a mock declaration, usually a mock module, contains something, that is declared in the TestBed module directly.

Let's imagine a situation that we have a module which exports declarations, for example directives, we need in our test. At the same time, we have another module that has other declarations, our component depends on, we would like to turn into a mock object, but, at the same time, it imports the same module we want to keep as it is via an import in TestBed.

TestBed.configureTestingModule({
imports: [
SharedModule,
MockModule(ModuleWithServicesAndSharedModule),
],
declarations: [
ComponentToTest,
],
});

The problem is clear: when we create the mock module, MockModule recursively creates its mock dependencies, and, therefore, it creates a mock class of SharedModule. Now imported and mock declarations are part of 2 modules.

To solve this, we need to let MockModule know, that SharedModule should stay as it is.

There are good and bad news. The bad news is that MockModule does not support that, but the good news is that ng-mocks has MockBuilder for such a complicated case. The only task now is to rewrite beforeEach to use MockBuilder instead of MockModule.

A possible solution might look like:

beforeEach(() => {
return MockBuilder(MyComponent, ModuleWithServicesAndSharedModule)
.keep(SharedModule);
});

The configuration says that we want to test ComponentToTest, which depends on SharedModule and ModuleWithServicesAndSharedModule, but SharedModule should stay as it is.

Now, during the building process, MockBuilder will keep SharedModule as it is, although it is a dependency of the mock module, and that avoids declarations of the same things in 2 modules.

More detailed information how to use it you can find in the section called MockBuilder.