单元测试spyOn在angular2中的可观察服务

Sud*_*r V 12 unit-testing typescript angular

我有一个服务(ChildService),它依赖于另一个服务(InteractWithServerService).以后的服务(InteractWithServerService)用于进行服务器调用并返回"any"类型的observable.为简单起见,我们假设它返回了observable.我正在尝试为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;
    }
}
Run Code Online (Sandbox Code Playgroud)

ServerInteractionService

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

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

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");
    });
});
Run Code Online (Sandbox Code Playgroud)

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

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");
    });
});
Run Code Online (Sandbox Code Playgroud)

我错过了一些明显的东西吗

Pau*_*tha 22

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

因为你仍然有服务providers,所以Angular仍然试图创建它

providers: [
 InteractWithServerService,
    ChildService],
Run Code Online (Sandbox Code Playgroud)

你可以做什么而不是创建一个模拟只是做类似的事情

providers: [
  { 
    provide: InteractWithServerService,
    useValue: { get: Observable.of(..) }
  }
]
Run Code Online (Sandbox Code Playgroud)

这是你正在使用useValue哪个提供任何对象.这将是注入时使用的值.在上面的例子中,它只是你的mock方法的一些任意对象.

如果你想间谍,以便你可以提供不同的值,你可以注入InteractWithServerService,然后做

spyOn(service, 'get').and.returnValue(Observable.of(...))
// do test
Run Code Online (Sandbox Code Playgroud)

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

{ provide: Http, useValue: {} }
Run Code Online (Sandbox Code Playgroud)

现在InteractWithServerService它将工作(只是将类添加到您当前拥有的提供程序).而你可以只是窥探它

let service = TestBed.get(InteractWithServerService);
spyOn(service, 'get').and.returnValue(..)
// do test
Run Code Online (Sandbox Code Playgroud)