首页 > 解决方案 > Angular-Testing:如何使用 TestBed 为服务类提供配置对象?

问题描述

我有一个需要将配置对象传递给服务的 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()andtoThrow()方法,但即使将TestBed.configureTestingModule()箭头函数放入期望中也不起作用。这样做不会引发错误。

有没有办法做到这一点?另外,有没有办法向服务提供配置对象以测试它是否将服务属性设置为正确的值?

标签: angularunit-testingtestingjasmine

解决方案


只需为配置对象提供一个值:

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当没有提供令牌的值时,我没有看到装饰配置对象的意义并抛出。您基本上是在重新实现默认未提供的逻辑。


推荐阅读