我在Karma上有一个Angular应用程序的工作设置。目前我正在测试2个不同的服务PerformanceService和DataService,所以我有2个文件,performance.service.spec.ts和data.service.spec.ts
两个文件都在初始化TestBed,并且还配置了在测试服务时使用的MockHttp。
TestBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
function createResponse(body) {
return Observable.of(
new Response(new ResponseOptions({ body: JSON.stringify(body) }))
);
}
class MockHttp {
get() {
return createResponse([]);
}
}
据我所知,这可以做一次,不需要为每一项服务都做,所以我创建了一个src / main.spec.ts并将那些代码移到那里,并将其从服务中删除。 / p>
现在我运行测试并且它不起作用,我收到错误TypeError: Cannot read property 'injector' of null
知道为什么会这样吗? main.spec.ts首先被执行,所以如果我没有弄错的话,一旦我们测试服务就应该初始化TestBed。
谢谢
答案 0 :(得分:0)
我们的团队遇到了同样的问题。一种解决方案是将TestBed初始化提取到一个单独的文件中并保护它,以便它只被初始化一次:
import { TestBed } from "@angular/core/testing";
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from "@angular/platform-browser-dynamic/testing";
export class TestBedInitializer {
static isInitialized: Boolean = false;
static getTestBed() {
if(!this.isInitialized) {
TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
this.isInitialized = true;
}
return TestBed;
}
}
然后您可以使用beforeAll块中的初始化程序来获取TestBed的实例:
import { TestBedInitializer } from './init';
describe('YourSystemUnderTest', () => {
let TestBed;
beforeAll(() => {
TestBed = TestBedInitializer.getTestBed();
});
beforeEach(() => TestBed.configureTestingModule({
imports: [...],
providers: [...]
}));
...
});
此解决方案的优势在于您不依赖于以任何特定顺序运行的测试套件。这使您可以单独或一次性运行套件,而无需更改代码。
答案 1 :(得分:-1)
没有必要创建自己的MockHttp
类,因为Angular已经创建了一个类:https://angular.io/docs/ts/latest/api/http/testing/index/MockBackend-class.html
示例用法是这样的:
describe( 'AppleService', () => {
let appleService: AppleService,
response: Response;
beforeEach( () => {
TestBed.configureTestingModule( {
providers: [
AppleService,
{ provide: XHRBackend, useClass: MockBackend },
{ provide: ComponentFixtureAutoDetect, useValue: true }
],
imports: [
HttpModule
]
} )
.compileComponents();
} );
it( 'getApples() should return mocked results', async(
inject( [ Http, XHRBackend ], ( http: Http, backend: MockBackend ) => {
backend.connections.subscribe( ( connection: MockConnection ) => {
expect( connection.request.url.match( /\/apple$/ ) ).not.toBe( null );
expect( connection.request.method ).toBe( RequestMethod.Get );
connection.mockRespond( response );
} );
let options = new ResponseOptions( { status: 200, body: [ testApple1, testApple2 ] } );
response = new Response( options );
appleService = new AppleService( resourceService, http );
appleService.getApples().subscribe( apples => {
expect( apples ).toEqual( [ testApple1, testApple2 ] );
} );
} ) ) );
} );
也可以使用 TestBed.get()
代替inject()
包装器。