Reputation: 73
I am trying to set up unit test for simple Angular 2 app. I walk into trouble, beacuse unit tests creates multiple instances of class. See the code below
app.component.ts
import { TestClass } from './test.class';
import { Service } from './service';
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: '<div></div>'
})
export class AppComponent {
constructor(private s: Service) {
let c = new TestClass();
}
}
test.class.ts
export class TestClass {
static counts = 0;
constructor() {
TestClass.counts++;
if (TestClass.counts > 1)
throw "Multiple TestClass instance";
}
}
app.component.spec.ts
import { Service } from './service';
import { AppComponent } from './app.component';
import { TestBed, ComponentFixture } from '@angular/core/testing';
let fixture: ComponentFixture<AppComponent>;
describe('AppComponent', function () {
beforeEach(() => {
fixture = TestBed.configureTestingModule({
declarations: [AppComponent],
providers: [Service]
}).createComponent(AppComponent);
});
afterEach(() => {
fixture.destroy();
});
it('1', () => {
expect(true).toBe(true);
});
it('2', () => {
expect(true).toBe(true);
});
});
The result of tests
[1] Error: Error in ./AppComponent class AppComponent_Host - inline template
:0:0 caused by: Multiple TestClass instance
Is there a way to delete class instance before run next "it"?
Upvotes: 2
Views: 2950
Reputation: 2584
The multiple instances of TestClass
are being created because AppComponent
is being created by TestBed
once for every it
block. In the above case that would be twice. afterEach
runs once after every it
block, There you can reset the static variable counts
describe('AppComponent', function () {
beforeEach(() => {
fixture = TestBed.configureTestingModule({
declarations: [AppComponent],
providers: [Service]
}).createComponent(AppComponent);
});
afterEach(() => {
fixture.destroy();
TestClass.counts = 0
});
......
This way you don't have to delete the TestClass
it self to reset the counts
variable
EDIT : Alternative method :
Since you are already destroying the component in the afterEach
block, you can use ngOnDestroy
life cycle hook on AppComponent
to reset the count variable there it self. The logic here being that if the component itself is destroyed, Then so is the instance of TestClass
. It has to be done this way as typescript does not have the concept of destructors
@Component({
selector: 'my-app',
template: '<div></div>'
})
export class AppComponent implements OnDestroy{
constructor(private s: Service) {
let c = new TestClass();
}
ngOnDestroy() {
TestClass.counts = 0;
}
}
Upvotes: 2