使用 Angular 2 注入依赖项的单元测试服务
Unit test service with injected dependency using Angular 2
我正在为具有依赖性的服务创建一个简单的单元测试。这是一项简单的服务,我开始使用它来帮助我了解最佳流程和结构。
我创建的单元测试有效,但 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>>'.
该服务在发出 HTTP post 请求的注入服务上执行方法 sendBody。我知道这里应该返回一个 Observable,但我认为模拟服务应该已经解决了这个 TypeScript 类型错误。
是否有更好的方法在仅测试服务时注入和模拟依赖项?
服务
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);
}
}
规格
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' });
})));
});
如果它必须return一个Observable,那么return一个Observable!
试试这个:
const MockReturnOrderResource = {
sendBody: (any: any) => Observable.of(any);
}
我已经使用不同的方法解决了这个问题。虽然它可能无法解决我遇到的类型错误,但它允许我监视注入的服务,这正是我想要的。
注入服务后,我使用 TestBed.get() 获取服务并将其分配给变量。
然后我可以监视注入的服务并针对调用该方法的参数进行测试。
更新后的规范如下。
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' })
})));
});
进一步阅读此解决方案:https://angular.io/guide/testing#testbedget
我正在为具有依赖性的服务创建一个简单的单元测试。这是一项简单的服务,我开始使用它来帮助我了解最佳流程和结构。
我创建的单元测试有效,但 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>>'.
该服务在发出 HTTP post 请求的注入服务上执行方法 sendBody。我知道这里应该返回一个 Observable,但我认为模拟服务应该已经解决了这个 TypeScript 类型错误。
是否有更好的方法在仅测试服务时注入和模拟依赖项?
服务
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);
}
}
规格
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' });
})));
});
如果它必须return一个Observable,那么return一个Observable!
试试这个:
const MockReturnOrderResource = {
sendBody: (any: any) => Observable.of(any);
}
我已经使用不同的方法解决了这个问题。虽然它可能无法解决我遇到的类型错误,但它允许我监视注入的服务,这正是我想要的。
注入服务后,我使用 TestBed.get() 获取服务并将其分配给变量。
然后我可以监视注入的服务并针对调用该方法的参数进行测试。
更新后的规范如下。
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' })
})));
});
进一步阅读此解决方案:https://angular.io/guide/testing#testbedget