18

我在尝试对角度服务进行单元测试时遇到问题。我想验证该服务是否正确调用了另一个注入其中的服务。

假设我有这个注入 ServiceInjected 的 ServiceToTest:

服务测试.service.ts

@Injectable()
export class ServiceToTest  {
    constructor(private _si: ServiceInjected) {}
    public init() {
      this._si.configure();
    }

}

ServiceInjected.service.ts

@Injectable()
export class ServiceInjected {
    constructor() {}
    public configure() {
    /*Some actions*/
    }

}

有了这些服务,现在我编写单元测试:

const serviceInjectedStub = {
  configure(): void {}
}


describe('ServiceToTest service Test', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [ServiceToTest ,
        { provide: ServiceInjected, useValue: serviceInjectedStub }]
    });
  });
  
  it('should be initialize the service injected', inject([ServiceToTest],
    (tService: ServiceToTest) => {
      spyOn(serviceInjectedStub, 'configure');
      tService.init();
      expect(serviceInjectedStub.configure).toHaveBeenCalled();
    }));

我预计我的测试是肯定的,但是我收到以下错误:

预期的间谍配置已被调用。

另一方面,如果我以这种方式将注入的服务设置为公开,它就可以正常工作:

private _si: ServiceInjected by public si: ServiceInjected
4

4 回答 4

40

您不会监视与您的 TestBed 相关的服务。从您的测试平台获取服务

beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [ServiceToTest ,
      { provide: ServiceInjected, useValue: serviceInjectedStub }]
  });
  injectedService = TestBed.get(ServiceInjected);
});

并对其进行测试

spyOn(injectedService, 'configure').and.returnValue(/* return same data type here */);
// ...
expect(injectedService.configure).toHaveBeenCalled();
于 2017-12-22T09:09:14.080 回答
6

或者您可以使用jasmine.createSpyObj并提供它,useValue如下所示:

describe('YourComponent', () => {

  let serviceInjectedSpy: jasmine.SpyObj<ServiceInjected>;

  beforeEach(async(() => {

     // notice here
     serviceInjectedSpy = jasmine.createSpyObj('ServiceInjected', ['configure']);

     TestBed.configureTestingModule({
        declarations: [YourComponent],
        providers: [
           {provide: ServiceInjected, useValue: serviceInjectedSpy}
        ],
        imports: [
         ...
        ]
     }).compileComponents().then(() => {
        fixture = TestBed.createComponent(YourComponent);
        component = fixture.componentInstance;
     });
  });

  it('should assert my test', () => {
       serviceInjectedSpy.configure.and.returnValue(/* what you want */);
       component.init();
       expect(serviceInjectedSpy.configure).toHaveBeenCalled();
  });

});
于 2019-04-03T12:38:48.927 回答
1

用这个:

spyOn(serviceInjectedStub, 'configure').and.returnValue(config); // 配置是一个模拟

于 2017-12-22T08:51:59.453 回答
0

从 Angular 9 你应该使用TestBed.inject; 那么您不需要将服务添加到提供者列表中。

let injectedService: ServiceInjected;
beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [ServiceToTest]
  });
  injectedService = TestBed.inject(ServiceInjected);
});

然后窥探它

// if you want to ignore the call
spyOn(injectedService, 'configure').and.callThrough();
// if you need to set stuff up
spyOn(injectedService, 'configure').and.callFake(async () => {/* some fake stuff */});

并做检查

expect(injectedService.configure).toHaveBeenCalled();
// ...
于 2022-02-19T20:07:58.310 回答