简体   繁体   English

测试服务角度

[英]Testing Service Angular

I am facing a problem with I have no clue how to solve it beacause I am so noobie with testing in front. 我不知道如何解决该问题,因为我对前面的测试非常满意。

Right now I am testing a service that have this code: 现在,我正在测试具有以下代码的服务:

import { Injectable } from '@angular/core';
import { EndpointLocatorService } from './endpointLocator.service';
import { Http, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class CancelAppService {

    constructor(private readonly http: Http,
        private readonly _endPointLocator: EndpointLocatorService) { }

    getScopeSignature(signatureToken: string) {
        const url = this._endPointLocator.locate('cancelApp');
        const language = sessionStorage.getItem('languageSession');
        const headers = new Headers({
            'Content-Type': 'application/json',
            'Accept-Language': language,
            'X-B3-TraceId': sessionStorage.getItem('requestID')
        });
        const body = JSON.stringify({ 'signatureToken': signatureToken });
        return this.http.post(url, body, { headers }).map(data => {
            return data.json();
        }).catch((error: any) => {
            return Observable.throw(new Error(error.status));
        });
    }
}

The testing file contains this: 测试文件包含以下内容:

import { TestBed } from '@angular/core/testing';
import { CancelAppService } from './cancelApp.service';
import { HttpModule } from '@angular/http';
import { EndpointLocatorService } from './endpointLocator.service';
import { AppConfig } from '../app.config';
import 'jasmine';

fdescribe('CancelAppService', () => {
    let cancelService: CancelAppService; // Add this
    let endLocator: EndpointLocatorService;
    const mockData = {
        "signature_token": "returnedToken"
    };
    const body = JSON.stringify({ 'signatureToken': 'givenToken' });
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [
                HttpModule
            ],
            providers: [
                CancelAppService,
                AppConfig,
                EndpointLocatorService
            ]
        });
        cancelService = TestBed.get(CancelAppService); // Add this
        endLocator = TestBed.get(EndpointLocatorService);
    });

    it('should be created', () => { // Remove inject()
        expect(cancelService).toBeDefined();
    });

    it('should call the service', () => {
        spyOn(endLocator, 'locate').and.returnValue('someUrl');
        spyOn(cancelService, 'getScopeSignature').and.callThrough();
        cancelService.getScopeSignature(body);
        expect(cancelService.getScopeSignature).toHaveBeenCalled();
    });

    it('should return a object', () => {
        (done: DoneFn) => {
            spyOn(endLocator, 'locate').and.returnValue('someUrl');
            spyOn(cancelService, 'getScopeSignature').and.returnValue(mockData);
            cancelService.getScopeSignature(body).subscribe(data => {
                expect(data).toEqual(mockData);
                done();
            });
        }
    });
});

The problem is that, when I try to test the returned data map, appears me like a success test, but the coverage says that I have no coveraged the lines of map, and catch. 问题是,当我尝试测试返回的数据地图时,看起来像是一次成功测试,但是覆盖率表明我没有覆盖地图的线条和捕捉范围。

在此处输入图片说明

Any idea what am I doing wrong? 知道我在做什么错吗? and how to solve it? 以及如何解决?

Thank you so much!! 非常感谢!!

You are mocking the service being tested, you should mock the service being used by your service EndpointLocatorService and maybe even HttpClient to minimize mocking. 您要模拟正在测试的服务,应该模拟服务EndpointLocatorService甚至HttpClient使用的服务,以最大程度地减少模拟。 You can verify that by stepping through your code. 您可以通过单步执行代码来验证。

Let me explain in the code why those lines are not hit. 让我在代码中解释为什么这些行没有被选中。

// In this example, the lines are hit, but after the test exited.
it('should call the service', () => {
    spyOn(endLocator, 'locate').and.returnValue('someUrl');
    spyOn(cancelService, 'getScopeSignature').and.callThrough();
    // Here you are calling a method yourself and checking that it was
    // called, it doesn't make sense, this test should make sure
    // You should check that your endLocator was called.
    // Note that because you are not waiting for the promise to resolve,
    // The test finishes before either callback is handled.
    cancelService.getScopeSignature(body);
    expect(cancelService.getScopeSignature).toHaveBeenCalled();
});


// In this example the lines in your test are never hit because you
// mocked it
it('should return a object', () => {
    (done: DoneFn) => {
        spyOn(endLocator, 'locate').and.returnValue('someUrl');
        // Here you are mocking getScopeSignature completely so it doesn't
        // Run any of your lines that you are trying to test
        // It just tests that you mocked it correctly
        spyOn(cancelService, 'getScopeSignature').and.returnValue(mockData);
        cancelService.getScopeSignature(body).subscribe(data => {
            expect(data).toEqual(mockData);
            done();
        });
    }
});

I can't rewrite your test so it actually tests it because it depends on how the EndpointLocatorService works and you may choose to mock it at that level also. 我无法重写您的测试,因此它实际上会对其进行测试,因为它取决于EndpointLocatorService工作方式,您也可以选择在该级别上对其进行模拟。 I typically choose to mock at the HttpClient level since I can copy paste responses from the network tab. 我通常选择在HttpClient级别进行模拟,因为我可以从“网络”标签复制粘贴响应。

The point is that you need to mock services used by your service, not the service itself. 关键是您需要模拟服务使用的服务,而不是服务本身。 You have the option to mock the direct services used by your component, or you can mock at a deeper level. 您可以选择模拟组件所使用的直接服务,也可以进行更深层次的模拟。 For example, your EndpointLocatorService may need to call HttpClient and you could choose to mock either service. 例如,您的EndpointLocatorService可能需要调用HttpClient ,您可以选择模拟其中一个服务。

See https://angular.io/guide/testing#httpclienttestingmodule and https://alligator.io/angular/testing-httpclient/ 参见https://angular.io/guide/testing#httpclienttestingmodulehttps://alligator.io/angular/testing-httpclient/

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

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