角度单元测试 - 使用TestBed

时间:2018-06-12 12:27:37

标签: angular karma-jasmine angular-test angular-unit-test angular-testing

我需要为以下DataService编写单元测试,

@Injectable()
export class DataService {
   constructor(private config: ConfigService, private http: HttpClient) {

   }

   .....

   someMethod(){
        let apiUrl = this.config.get('api').url;   // LINE 1
   }
}

ConfigService被注入DataService,其load函数从json文件获取配置。初始化应用程序时将调用此load函数。

export function configServiceFactory(config: ConfigService) {
    return () => config.load();
}

...

providers: [
        ConfigService,
        {
            provide: APP_INITIALIZER,
            useFactory: configServiceFactory,
            deps: [ConfigService],
            multi: true
        }
    ]

以下是data-service.spect.ts文件的一部分,

...

beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule
      ],
      providers: [DataService, ConfigService]
    });

    mock = TestBed.get(HttpTestingController);
    service = TestBed.get(DataService);
  });

....

所以当我运行测试时,在LINE 1我得到this.config.get('api')未定义。我可以理解,这是因为ConfigService没有从JSON加载数据。那么现在我如何使注入的服务也在单元测试期间进行异步调用?

1 个答案:

答案 0 :(得分:2)

编写单元测试时,您可能希望模拟您拥有的每个依赖项。您已通过导入HttpClientHttpClientTestingModule执行此操作,因此您需要对ConfigService执行相同操作。

有两种方法可以做到这一点。

1-假服务(存根)

export class ConfigServiceStub {
    get(input: string) {
        // return static value instead of calling an API
    }
}

...

beforeEach(() => {
    TestBed.configureTestingModule({
        imports: [
            HttpClientTestingModule
        ],
        providers: [DataService, 
                   {provide: ConfigService, useClass: ConfigServiceStub}
        ]
    });

    mock = TestBed.get(HttpTestingController);
    service = TestBed.get(DataService);
});

通过这种方式,您的DataService将不会调用真实的ConfigService,而是会调用get的{​​{1}}方法。使用ConfigServiceStub时,您无需担心其他依赖项Stub。您只需实现要覆盖的方法。

<强> 2-间谍

您可以在不想调用的方法上创建间谍。

ConfigService

即使在上面的示例中不会调用it('run some test', inject([DataService], (service: DataService) => { spyOn(service.config, 'get').and.returnValue('someString'); // run your tests here }); 方法,Angular仍然需要创建ConfigService.get的实例,在某些示例中可能很难这样做,或者可能导致创建太多其他服务用于简单测试。

我选择选项1

有关间谍的更多信息,请查看here