角度如何测试服务方法? [英] Angular how to test service methods?

查看:19
本文介绍了角度如何测试服务方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力学习如何编写测试。我不知道如何从服务模拟和测试方法。

我当前的服务文件如下:

import {Injectable} from '@angular/core';
import {HttpClient, HttpErrorResponse} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {catchError, map, tap} from 'rxjs/operators';
import {APICONFIG} from 'src/app/config/api.config';
import {Certificate} from 'src/app/models';

const APIURL = `${APICONFIG.base}/education/certificate`;

@Injectable()
export class CertificateService {

  constructor(private http: HttpClient) {
  }

  getAllUserCertificates(uuid: string): Observable<Certificate []> {
    if (!uuid) {
      return new Observable<Certificate []>();
    }
    return this.http.get<Certificate []>(`${APIURL}/${uuid}`).pipe(
      tap(data => console.log("All user certificates: ", JSON.stringify(data))),
      map(this.parseCertificateData),
      catchError(this.handleError)
    )
  };

  saveUserCertificates(certificates: Certificate[]): Observable<Certificate[]> {
    return this.http.post<Certificate[]>(APIURL, certificates).pipe(
      tap(data => console.log("All saved user certificates: ", JSON.stringify(data))),
      map(this.parseCertificateData),
      catchError(this.handleError)
    )
  };

  parseCertificateData(rawCertificates: any): Certificate[] {
    return Object.keys(rawCertificates).map(key => {
      let certificate = new Certificate(
        rawCertificates[key].model.institute,
        rawCertificates[key].model.name,
        rawCertificates[key].model.description,
        rawCertificates[key].model.achievementDate,
        rawCertificates[key].model.expirationDate,
        rawCertificates[key].model.url,
        rawCertificates[key].id
      );
      console.log(rawCertificates[key]);
      return certificate;
    });
  };

  private handleError(err: HttpErrorResponse) {
    let errorMessage = "";
    if (err.error instanceof ErrorEvent) {
      errorMessage = `An error occurred: ${err.error.message}`;
    } else {
      errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`
    }
    console.error(errorMessage);
    return throwError(errorMessage);
  };
}

和我写的测试如下:

import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing";
import { Certificate } from "src/app/models";
import { APICONFIG } from "src/app/config/api.config";
import { TestBed } from "@angular/core/testing";
import { CertificateService } from "../certificate.service";


describe('CertificateService', ()=>{
    let httpTestingController: HttpTestingController;
    const APIURL = `${APICONFIG.base}/education/certificate`;

    let certificatesJson = 
    [
        {
            "id": "1",
            "model": {
                "institute": "Institute",
                "name": "Certificaat",
                "description": "Description",
                "achievementDate": "2021-12-14T16:27:02.000+00:00",
                "expirationDate": "2021-12-14T16:27:08.000+00:00",
                "url": "url"
            }
        },
        {
            "id": "2",
            "model": {
                "institute": "Institute2",
                "name": "Certificaat2",
                "description": "Description2",
                "achievementDate": "2021-12-14T16:27:02.000+00:00",
                "expirationDate": "2021-12-14T16:27:08.000+00:00",
                "url": "url2"
            }
        }
    ]

    let certificatesParsed: Certificate[] = [{id: "1", institute: "Institute", name: "Certificaat",  description: "Description", achievementDate: "2021-12-14T15:59:01.000+00:00", expirationDate: "2021-12-14T15:59:11.000+00:00", url: "url"},
                                            {id: "2", name: "Certificaat", institute: "Institute", description: "Description", achievementDate: "2021-12-14T15:59:01.000+00:00", expirationDate: "2021-12-14T15:59:11.000+00:00", url: "url"}];
    

    beforeEach(()=>{
        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule],
            providers: [CertificateService]
        });
        httpTestingController = TestBed.inject(HttpTestingController);
    });

    describe('getAllUserCertificates', () =>{
        it('should return all certificate objects from user', () => {
            let id = "1";
            const certificateService = TestBed.inject(CertificateService);
            certificateService.getAllUserCertificates(id).subscribe(certificates => {
                expect(certificates.length).toBe(2);
            });

            const req = httpTestingController.expectOne(`${APIURL}/${id}`);
            expect(req.request.method).toBe('GET');
            
            req.flush(certificatesJson);
            httpTestingController.verify();
        });

        it('should create new observable if id is null', () => {
            let id = "";
            const certificateService = TestBed.inject(CertificateService);
            const spy = spyOn(certificateService, 'getAllUserCertificates').and.callThrough();
            certificateService.getAllUserCertificates(id).subscribe();

            expect(spy.calls.count()).toEqual(1);
     
            httpTestingController.verify();
        });
    })

    describe('saveUserCertificates', () =>{
        it('should post correct certificate objects', () => {
            
            const certificateService = TestBed.inject(CertificateService);
            certificateService.saveUserCertificates(certificatesParsed).subscribe(certificates => {
                expect(certificates.length).toBe(2);
            });

            const req = httpTestingController.expectOne(APIURL);
            expect(req.request.method).toBe('POST');
            
            req.flush(certificatesJson);
            httpTestingController.verify();
        });
    })

    describe('parseCertificateData', ()=>{
        it('should parse data into certificate objects', () => {

            const certificateService = TestBed.inject(CertificateService);
            let certificates: Certificate[] = certificateService.parseCertificateData(certificatesJson);
            
            expect(certificates.length).toBe(2);
            expect(certificates[0].institute).toBe("Institute");
            expect(certificates[0].name).toBe("Certificaat");
            expect(certificates[0].description).toBe("Description");
            expect(certificates[0].url).toBe("url");
            expect(certificates[1].institute).toBe("Institute2");
            expect(certificates[1].name).toBe("Certificaat2");
            expect(certificates[1].description).toBe("Description2");
            expect(certificates[1].url).toBe("url2");
        });
    })
    
    describe('handleError', ()=>{
        it('should handle bad request', () => {
            let id = "11";
            let response: any;
            let errResponse: any;
            const mockErrorResponse = { status: 400, statusText: 'Bad Request' };
            const data = `Server returned code: 400, error message is: Http failure response for ${APIURL}/11: 400 Bad Request`;
            const certificateService = TestBed.inject(CertificateService);

            certificateService.getAllUserCertificates('11').subscribe(res => response = res, err => errResponse = err);
            httpTestingController.expectOne(`${APIURL}/${id}`).flush(data, mockErrorResponse);
            expect(errResponse).toBe(data);
        });

        it('should handle event error', () => {
            let id = "11";
            let response: any;
            let errResponse: any;
            const errorInitEvent: ErrorEventInit = {
                error : new Error('Error'),
                message : 'Error'
            };

            const mockErrorResponse = { status: 400, statusText: 'Bad Request'};
            const data = new ErrorEvent('MyErrEventType', errorInitEvent);
            
            const certificateService = TestBed.inject(CertificateService);

            certificateService.getAllUserCertificates('11').subscribe(res => response = res, err => errResponse = err);
            httpTestingController.expectOne(`${APIURL}/${id}`).flush(data, mockErrorResponse);
            expect(errResponse).toBe('An error occurred: Error');
        });
    })

})

我的业力的console.log当前充满错误:

出现错误:错误 以及 服务器返回代码:400,错误消息为:URL 400的HTTP失败响应错误请求。 感觉我用的是真正的服务,而不是被嘲笑的服务。能告诉我做这件事的正确方法是什么吗?

谢谢您的帮助,祝您周末愉快。

推荐答案

不能确切确定导致测试失败的原因,但请尝试以下操作:

里面先beforeEach挡路后httpTestingController = TestBed.inject(HttpTestingController);放此行certificateService = TestBed.inject(CertificateService); 。 在OFC顶部声明certificateService

现在您在每个it挡路中都不需要相同的启动代码const certificateService = TestBed.inject(CertificateService);

还可以在beforeEach之后定义挡路,您可以在其中执行以下操作(&GLOBAL";afterEach): httpTestingController.verify();(又是干原理)。

请告诉我这是否有帮助。

这篇关于角度如何测试服务方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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