【问题标题】:Unit testing with private service injected using jasmine angular2使用 jasmine angular2 注入私有服务的单元测试
【发布时间】:2018-06-04 22:12:50
【问题描述】:

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

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

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

【问题讨论】:

  • github.com/angular/angular/issues/10788。您可以简单地注入真正的服务并对其进行监视。或者根本不使用 DI 并使用new ServiceToTest(stub) 来测试服务。或者按照问题中的说明使用 useFactory。

标签: angular karma-jasmine angular-services injectable spyon


【解决方案1】:

您不会监视与您的 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();

【讨论】:

  • 谢谢老兄!!我今天17点放假! :p
  • 没问题,尽情享受吧:D
  • 这是我遗漏的重要信息,谢谢队友
  • @amansinghgusain 作为旁注,您不必使用测试台来获取它,您可以简单地在组件中使用数组表示法:injectedService = component['myService']。甚至可以使用私有属性
  • 由于某种原因,这对我不起作用。我仍然知道该服务没有被调用,它肯定会在 ngOnInit 中被调用。
【解决方案2】:

或者您可以使用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();
  });

});

【讨论】:

    【解决方案3】:

    使用这个:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-11
      • 1970-01-01
      • 2016-10-31
      • 1970-01-01
      • 2018-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多