我正在尝试测试我的模块的一个构造函数中的代码。基本上,模块(名为GraphqlModule
)配置服务(名为Graphql
)并提供它。配置发生在模块的构造函数中。
这是我用来测试模块的代码。
it('should use the GraphqlConfigs and ServerConfigs', (done: DoneFn) => {
// Adding spies to Config classes
let serverConfigs = new ServerConfigs();
let serverDomainSpy = spyOnProperty(serverConfigs, 'ServerDomain', 'get').and.callThrough();
let serverPortSpy = spyOnProperty(serverConfigs, 'ServerPort', 'get').and.callThrough();
let gqlConfigs = new GraphqlConfigs();
let protocolSpy = spyOnProperty(gqlConfigs, 'EndpointProtocol', 'get').and.callThrough();
let endpointNameSpy = spyOnProperty(gqlConfigs, 'EndpointName', 'get').and.callThrough();
TestBed.configureTestingModule({
imports: [ GraphqlModule ],
providers: [
{provide: ServerConfigs, useValue: serverConfigs}, // Replacing real config classes with the ones spied on.
{provide: GraphqlConfigs, useValue: gqlConfigs}
]
}).compileComponents().then(() => {
// This line seems to make Angular instantiate GraphqlModule
const graphql = TestBed.get(Graphql) as Graphql;
expect(serverDomainSpy.calls.count()).toBe(1, 'ServerConfigs.ServerDomain was not used.');
expect(serverPortSpy.calls.count()).toBe(1, 'ServerConfigs.ServerPort was not used.');
expect(protocolSpy.calls.count()).toBe(1, 'GraphqlConfigs.EndpointProtocol was not used.');
expect(endpointNameSpy.calls.count()).toBe(1, 'GraphqlConfigs.EndpointName was not used.');
done();
});
});
原样,测试通过并运行,但如果我不使用以下(无用)行const graphql = TestBed.get(Graphql) as Graphql;
,GraphqlModule
会在执行测试后实例化,这会导致测试失败。 / p>
由于提供GraphqlModule
服务的Graphql
,我知道Angular中有一些延迟加载算法,当我执行TestBed.get(Graphql)
时会触发。这很好......我的问题是,有没有办法让我的模块以更强烈的显式方式加载?
这是GraphqlModule类定义:
imports...
@NgModule({
imports: [
CommonModule,
HttpClientModule,
ApolloModule,
HttpLinkModule
],
declarations: [],
providers: [
Graphql, // Is an alias for Apollo
GraphqlConfigs
]
})
export class GraphqlModule {
constructor(
@Optional() @SkipSelf() parentModule: GraphqlModule,
graphql: Graphql,
httpLink: HttpLink,
serverConfigs: ServerConfigs,
graphqlConfigs: GraphqlConfigs
) {
// Making sure this is not imported twice.
// https://angular.io/guide/ngmodule#prevent-reimport-of-the-coremodule
if (parentModule) {
throw new Error(
'GraphqlModule is already loaded. Import it in the '+CoreModule.name+' only.');
}
// Gql setup:
const gqlHttpLink = httpLink.create({
uri: GraphqlModule.buildEndpointUrl(serverConfigs, graphqlConfigs)
});
graphql.create({
link: gqlHttpLink,
cache: new InMemoryCache(),
});
}
private static buildEndpointUrl(serverConfigs: ServerConfigs, graphqlConfigs: GraphqlConfigs): string {
return graphqlConfigs.EndpointProtocol + // eg. http://
serverConfigs.ServerDomain+":"+serverConfigs.ServerPort+'/' + // eg. example.com:80/
graphqlConfigs.EndpointName; // eg. graphql
}
}
答案 0 :(得分:2)
Graphql
已在GraphqlModule
构造函数中实例化为根注入器,并且GraphqlModule
在TestBed imports
中指定时会被急切地实例化。没有涉及延迟加载。
正如this answer中所述,TestBed注入器在第一次inject
回拨电话或TestBed.get
或TestBed.createComponent
电话上实例化。注射器在第一次注射之前不存在,因此不要有任何模块或提供者实例。由于几乎所有TestBed测试都会在it
或beforeEach
中至少执行其中一项调用,因此通常不会出现此问题。
由于此测试中不需要graphql
实例,为了使测试通过,它可以只是:
TestBed.get(Injector);
或者:
TestBed.get(TestBed);
此外,.compileComponents().then(() => { ... })
和done()
是不必要的,测试不涉及组件并且是同步的。
需要手动实例化注入器的事实表明此测试不需要TestBed,尽管它有用,因为可以测试GraphqlModule
构造函数DI注释,包括{{1}的注释}。