在angular2中进行单元测试spyOn的可观察服务 [英] unit testing spyOn observable service in angular2

查看:582
本文介绍了在angular2中进行单元测试spyOn的可观察服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个服务(ChildService),该服务依赖于另一个服务(InteractWithServerService).后者服务(InteractWithServerService)用于进行服务器调用并返回"any"类型的可观察对象.为了简单起见,我们假设它返回一个可观察的对象.我正在尝试为ChildService编写单元测试.

I have a service (ChildService) which depends on another service (InteractWithServerService). The latter service (InteractWithServerService) is used to make server calls and return an observable of "any" type. For simplicity let's assume it returns an observable. I am trying to write a unit test for ChildService.

ChildService

ChildService

@Injectable()
export class ApplicationService {
    constructor(private  interactWithServerService:InteractWithServerService){;}

    public GetMeData():string {
        var output:string;       
        this.interactWithServerService.get("api/getSomeData").
           subscribe(response =>{console.log("server response:", response);
           output=response});        
         return output;
    }
}

ServerInteractionService

ServerInteractionService

@Injectable()
export class InteractWithServerService {        
    constructor(private http: Http) {
        ;
    }    
    get(url: string): Observable<any> {        
        return this.http.get(this.url);
    }       
}

当我模拟依赖服务时,测试用例工作正常.即

The test case works fine when I mock the dependent service. i.e.,

class MockInteractWithServerService {
    get() {
        return Observable.of("some text");
    }           
}

describe('Service:ChildService', () => {
    let childService: ChildService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
             { provide: InteractWithServerService, useClass: MockInteractWithServerService },
                ChildService],
        });


    beforeEach(inject([ChildService], (actualService: ChildService) => {
        childService= actualService;        
    }));

    fit('should call server-call testCall()', () => {
        let actualReturnvalue= childService.GetMeData();        
        expect(actualReturnvalue).toBe("some text");
    });
});

上述方法不是首选方法,因为我可能最终会为"n"个依赖项编写"n"个模拟类.所以我想使用spyOn创建我的单元测试. 但是,该测试用例无法正常工作,并引发错误:Http的没有提供者!".虽然我理解错误是什么,但是我想知道为什么会抛出错误,尽管我在监视依赖服务.看起来"spyOn"无法正常工作.

The above method is not preferred as I might end up writing "n" mock classes for "n" dependencies. So I want to create my unit tests using spyOn. However, the test case doesn't work and throws "Error: No provider for Http!". While I understand what the error is, I would like to know why it is thrown although I am spying on the dependent service. Looks like the "spyOn" is not working.

describe('Service:ChildService', () => {
    let childService: ChildService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
             InteractWithServerService,
                ChildService],
        });

        spyOn(InteractWithServerService.prototype, 'get').and
             .callFake(()=>      
          {return Observable.of("some text");});       
    });
    beforeEach(inject([ChildService], (actualService: ChildService) => {
        childService= actualService;        
    }));

    fit('should call server-call testCall()', () => {
        let actualReturnvalue= childService.GetMeData();        
        expect(actualReturnvalue).toBe("some text");
    });
});

我缺少明显的东西吗?

推荐答案

但是,该测试用例不起作用,并抛出错误:Http的没有提供者!".

However, the test case doesn't work and throws "Error: No provider for Http!".

因为您仍然在providers中拥有该服务,所以Angular仍试图创建它

Because you still have the service in the providers, so Angular is trying to create it still

providers: [
 InteractWithServerService,
    ChildService],

除了创建模拟类 外,您可以做的只是做类似的事情

What you can do instead of creating a mock class is to just do something like

providers: [
  { 
    provide: InteractWithServerService,
    useValue: { get: Observable.of(..) }
  }
]

在这里,您正在使用提供任何对象的useValue.那将是注射时使用的值.在上述情况下,它只是您的模拟方法中的任意对象.

Here's you're using useValue which provide any object. That will be the value used when injected. In the case above, it is just some arbitrary object with your mock method.

如果您想监视以便提供不同的值,可以注入InteractWithServerService,然后执行

If you want to spy so that you can provide different values, you could inject the InteractWithServerService, and then do

spyOn(service, 'get').and.returnValue(Observable.of(...))
// do test

您可以做的另一件事是用一个虚拟对象模拟Http

Another thing you could do is mock the Http with a dummy object

{ provide: Http, useValue: {} }

现在InteractWithServerService将可以正常工作(只需将类添加到您当前拥有的提供者中).而且你可以监视它

Now the InteractWithServerService will work (just adding the class to the providers` like you currently have). And you can just spy on it

let service = TestBed.get(InteractWithServerService);
spyOn(service, 'get').and.returnValue(..)
// do test

这篇关于在angular2中进行单元测试spyOn的可观察服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆