简体   繁体   English

使用Angular 2注入依赖项的单元测试服务

[英]Unit test service with injected dependency using Angular 2

I'm creating a simple unit test for a service that has a dependency. 我正在为具有依赖项的服务创建一个简单的单元测试。 It is a simple service that I am starting on to help to get my head around the best process and structure. 我将开始提供这项简单服务,以帮助您更好地了解最佳流程和结构。

The unit test I have created works but TypeScript throws an error. 我创建的单元测试有效,但TypeScript引发错误。

Argument of type '{ order_id: string; user: string; }' is not assignable to parameter of type 'Expected<Observable<any>>'.
Object literal may only specify known properties, and 'order_id' does not exist in type 'Expected<Observable<any>>'.

The service executes the method sendBody on the injected service which makes a HTTP post request. 该服务在发出HTTP发布请求的注入服务上执行sendBody方法。 I understand an Observable should be returned here but I would have thought the mock service should have resolved this TypeScript type error. 我知道应在此处返回一个Observable,但我会认为模拟服务应该已经解决了此TypeScript类型错误。

Is there a better way to inject and mock dependencies when testing services only? 仅在测试服务时,有没有更好的方法来注入和模拟依赖项?

Service 服务

export class ReturnOrderService {

    constructor(private _ReturnOrderResource: ReturnOrderResource) { }

    updateOrderStatus(orderId: string, user: string) {
        let body = {};

        if (orderId !== undefined && user !== undefined) {
            body["order_id"] = orderId;
            body["user"] = user;
        }

        return this._ReturnOrderResource.sendBody(body);
    }

}

Spec 规格

const MockReturnOrderResource = {
sendBody: function(body) {
    return body;
  }
}

describe('ReturnsComponent', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({ providers: [
       ReturnOrderService,
       { provide: ReturnOrderResource, useValue: MockReturnOrderResource }
      ] });
  });

  it('#updateOrderStatus should create an object literal from arguments',
    async(inject([ReturnOrderService], (service: ReturnOrderService) => {
      expect(service.updateOrderStatus("10006886","Mr Bungle")).toEqual({ order_id: '10006886', user: 'Mr Bungle' });
  })));

});

If it must return an Observable, then return an Observable ! 如果必须返回一个Observable,则返回一个Observable!

Try this : 尝试这个 :

const MockReturnOrderResource = {
    sendBody: (any: any) => Observable.of(any);
}

I've worked through a solution for this using a different approach. 我已经使用不同的方法解决了这个问题。 While it may not resolve the type error I was experiencing, it allows me to spyOn the injected service which is exactly what I was after. 虽然它可能无法解决我遇到的类型错误,但它使我可以窥探注入的服务,而这正是我所追求的。

After injecting the service I get the service using TestBed.get() and assign this to a variable. 注入服务后,我使用TestBed.get()获得服务并将其分配给变量。

I can then spyOn the injected service and test against the argument(s) the method was called with. 然后,我可以监视注入的服务并针对调用该方法的参数进行测试。

The updated spec below. 以下是更新的规格。

const MockReturnOrderResource = {
  sendBody: function(body) {
    return body;
  }
}

describe('ReturnsComponent', () => {
  let _ReturnOrderResource;

  beforeEach(() => {
    TestBed.configureTestingModule({ providers: [
       ReturnOrderService,
       { provide: ReturnOrderResource, useValue: MockReturnOrderResource }
      ] });
    _ReturnOrderResource = TestBed.get(ReturnOrderResource);
  });

  it('#updateOrderStatus should pass an object literal as an argument',
    async(inject([ReturnOrderService], (service: ReturnOrderService) => {
    spyOn(service, "updateOrderStatus").and.callThrough();
    spyOn(_ReturnOrderResource, "sendBody").and.callThrough();
    service.updateOrderStatus("10006886","Mr Bungle");
    expect(_ReturnOrderResource.sendBody).toHaveBeenCalledWith({ order_id: '10006886', user: 'Mr Bungle' })
  })));

});

For further reading around this solution: https://angular.io/guide/testing#testbedget 有关此解决方案的更多信息,请访问: https : //angular.io/guide/testing#testbedget

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM