Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing angular2 component with imported module

I am trying to write a test on a component which uses angular-material2, but when I add it to my testModule declarations I get:

Error: Template parse errors:
    'md-card-title' is not a known element:
    1. If 'md-card-title' is an Angular component, then verify that it is part of this module.
    2. If 'md-card-title' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.

Adding MaterialModule to the declarations throws `Error: Unexpected module 'MaterialModule' declared by the module

DynamicTestModule' in config/spec-bundle.js (line 24994)

This is what my spec file looks like:

  beforeEach(() => TestBed.configureTestingModule({
    declarations: [],
    providers: [
      { provide: DataService, useValue: mockDataService },
      { provide: ActivatedRoute, useClass: MockActivatedRoute },
      { provide: Router, useValue: mockRouter },
      CellViewComponent
    ]
  }));

adding CellViewComponent to the declarations array causes the error to throw.

like image 541
George Edwards Avatar asked Oct 26 '16 17:10

George Edwards


People also ask

Can we declare a component in multiple modules in Angular?

You will need another component (say ProjectComponent) for Project Module declaration. As shared module is imported into you project module you can directly use overlay component in ProjectComponent template, using selector. Hope this helps.

How does Jasmine define Angular spec?

We use the Jasmine-provided it function to define a spec. The first parameter of it is a text description of what the spec will be testing — in this case we have a defined component. The second parameter is a function that will run the test. We then use Jasmine's expect function to define our expectation.


2 Answers

When you use the TestBed.configureTestingModule, you're create a module from scratch for the test environment. So what ever you would need in the real application for the CellViewComponent to work, you also need to configure it in the testing module.

In your case, you're missing the Material card component. In the app you probably either imported the MaterialModule or the MdCardModule into your AppModule. So you need to do the same in the testing module

beforeEach(() => TestBed.configureTestingModule({
  imports: [ MaterialModule /* or MdCardModule */ ],
  declarations: [  CellViewComponent ],
  providers: [
    { provide: DataService, useValue: mockDataService },
    { provide: ActivatedRoute, useClass: MockActivatedRoute },
    { provide: Router, useValue: mockRouter },
  ]
}));
like image 118
Paul Samsotha Avatar answered Oct 23 '22 05:10

Paul Samsotha


This is a real problem: you can mock everything but the imported component's selector.

There is an easy way. It allows to avoid importing the modules, instead you can just disable this kind of errors.

Just add this to your module:

import { NO_ERRORS_SCHEMA } from '@angular/core';

...

TestBed.configureTestingModule({
  schemas: [ NO_ERRORS_SCHEMA ],
  ...

Angular2 docs link

Yes, it won't help if you want to make integration (not isolated) tests, but it perfectly works for isolated ones.

Still even if you would decide to import a module I think it might be more correct to import the mock module with all implemented selectors instead.

like image 40
smnbbrv Avatar answered Oct 23 '22 05:10

smnbbrv