While writing unit tests I hit to strange case for which I don't understand where the problem is.
I've prepared short code for reproducing:
TestInjectable - simple injectable class
@Injectable()
class TestInjectable {
testProperty = 'testValue';
}
TestComponent - small component that uses TestInjectable
@Component({
providers: [TestInjectable],
template: ''
})
class TestComponent {
constructor(private injectable: TestInjectable) {
}
doTest() {
return this.injectable.testProperty;
}
}
Unit test
describe('Test TestComponent', () => {
beforeEach(async(() => {
let testInjectableMock: TestInjectable = new TestInjectable();
testInjectableMock.testProperty = 'valueInMock';
TestBed.configureTestingModule({
providers: [{provide: TestInjectable, useValue: testInjectableMock}],
declarations: [TestComponent]
}).compileComponents();
}));
it('should do something', () => {
let fixture: ComponentFixture<TestComponent> = TestBed.createComponent(TestComponent);
let component: TestComponent = fixture.componentInstance;
expect(component.doTest()).toBe('valueInMock');
});
});
Since I have testInjectableMock
to which I set valueInMock
I would expect that component would return this value. The problem is that component is returning testValue
which is default value and test fails with:
Expected 'testValue' to be 'valueInMock'.
It sounds like TestBed
is creating another instance of TestInjectable
even if I provided instance using useValue
property.
providers: [{provide: TestInjectable, useValue: testInjectableMock}]
Has anyone idea if I missed something or where the catch is and how to convince TestBed
to use mock instance?
TestBed. createComponent() creates an instance of the BannerComponent , adds a corresponding element to the test-runner DOM, and returns a ComponentFixture .
The TestBed is the first and largest of the Angular testing utilities. It creates an Angular testing module — a @NgModule class — that you configure with the configureTestingModule method to produce the module environment for the class you want to test.
TestBed is a mock environment to run Angular2 component tests without the browser.
Angular DI clones objects provided by useValue
and from the looks of it, does it incorrectly:
https://github.com/angular/angular/issues/10788
You should use factory instead:
TestBed.configureTestingModule({
providers: [{provide: TestInjectable, /*-->*/ useFactory: () => testInjectableMock}],
declarations: [TestComponent]
}).compileComponents();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With