我有一个Angular服务,需要将配置对象传递给该服务:
// my.module.ts
@NgModule({ ... })
export class MyModule {
static forRoot(config: MyServiceConfig): ModuleWithProviders {
return {
ngModule: MyModule,
providers: [{ provide: MyServiceConfig, useValue: config }],
};
}
}
//my.service.ts
export class MyService {
constructor(private _http: HttpClient, @Optional() config: MyServiceConfig) {
if (config) {
if (!config.attr1) {
throw new Error('You must provide the attr1 to use this Module.');
} else if (!config.attr2) {
throw new Error('You must provide the attr2 to use this Module.');
} else {
this.attr1 = config.attr1;
this.attr2 = config.attr2;
}
} else {
throw new Error(
'You must provide a MyServiceConfig object with the attr1 and the attr2 to use this module.',
);
}
}
}
这一切都可行,但是我想围绕向该服务提供该配置对象编写一些测试。我在测试文件中有以下beforeEach
,当未提供配置对象时,它按预期抛出了错误:
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [FeedbackService],
});
});
但是当我尝试将其移出beforeEach
并进行单个测试时,我无法正确地抛出错误。如果完全按照上面的方式调用它,但在测试中,它将:
it('should do something', () => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [FeedbackService],
});
});
我在try/catch
块中尝试了上述操作,试图捕获错误,但这给了我误报。我尝试了expect(() => {}).toThrowError()
和toThrow()
方法,但是即使将TestBed.configureTestingModule()
放在期望的箭头函数中也无法正常工作。这样就不会引发错误。
有没有办法做到这一点?另外,是否有一种方法可以向服务提供配置对象,以测试是否将服务属性设置为正确的值?
答案 0 :(得分:1)
只需为config对象提供一个值:
describe("FeedbackService", ()=>{
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [FeedbackService]
});
});
describe("when config object is provided", ()=>{
let dummyConfig : Object;
beforeEach(()=>{
dummyConfig = {/* set some properties*/};
TestBed.overrideProvider(MyServiceConfig, {useValue: dummyConfig});
});
it("should not explode", ()=>{
// a test in which the config object is dummyConfig
});
});
});
边注::我没有看到用@Optional
装饰配置对象的意义,并且在没有提供令牌值的情况下抛出该问题。您基本上是在重新实现默认未提供的逻辑。
答案 1 :(得分:0)
我使用了@ Jota.Toledo的一些答案并进行了编辑,以获取以下测试文件:
import { TestBed } from '@angular/core/testing';
import { MyService } from './my.service';
import { MyServiceConfig } from './my-service-config';
describe('MyService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [MyService],
});
});
describe('config object provided', () => {
let config: MyServiceConfig;
const attr1 = 'https://my-test-api.test.com';
const attr2 = 'testing';
beforeEach(() => {
config = null;
});
it('should use the values passed in the config for the attr1 and attr2', () => {
config = { attr1, attr2 };
TestBed.overrideProvider(MyService, { useFactory: () => new MyService(null, config) });
const service: MyService = TestBed.get(MyService);
expect(service.attr1).toBe(attr1);
expect(service.attr2).toBe(attr2);
});
it('should throw an error if config object is provided but not the attr1 attribute', () => {
try {
config = { attr1: null, attr2 };
TestBed.overrideProvider(MyService, { useFactory: () => new MyService(null, config) });
const service: MyService = TestBed.get(MyService);
} catch (e) {
expect(e.message).toBe('You must provide the api URL to use this module.');
}
});
it('should throw an error if config object is provided but not the attr2 attribute', () => {
try {
config = { attr1, attr2: null };
TestBed.overrideProvider(MyService, { useFactory: () => new MyService(null, config) });
const service: MyService = TestBed.get(MyService);
} catch (e) {
expect(e.message).toBe('You must provide the feedback source to use this module.');
}
});
});
describe('config object not provided', () => {
beforeEach(() => {
TestBed.overrideProvider(MyService, { useFactory: () => new MyService(null, null) });
});
it('should throw an error if no config object provided', () => {
try {
const service: MyService = TestBed.get(MyService);
} catch (e) {
expect(e.message).toBe(
'You must provide a MyServiceConfig object with the attr1 and the attr2 to use this module.',
);
}
});
});
});
这应该在应该发生的时候正确地抛出了错误,并且我能够检查message属性以确保它在正确的时间抛出了正确的错误。