【问题标题】:Service undefined when mocking inside Pipe unit test在管道单元测试中模拟时服务未定义
【发布时间】:2018-03-20 22:16:01
【问题描述】:

我正在尝试在 Pipe 的单元测试中模拟一项服务。我面临的问题是,即使遵循了多个指南并使用了多种方法,我在执行测试时仍然会收到 TypeError: Cannot read property 'transformDateToApi' of undefined 错误。

我见过其他人在组件上执行此任务,但对于 Pipe,它略有不同,对吧?

date.pipe.spec.ts

import { TestBed } from '@angular/core/testing';
import { DatePipe } from './date.pipe';
import { DateFormat } from '@app/enums';
import { ApiService } from '@app/services';
import { MainService } from '@app/state';

class MockApiService extends ApiService {
    transformDateToApi(date: Date = new Date()): string {
        return '13-08-1996T22:10:32';
    }
}

describe('DatePipe', () => {
    const testDate = new Date('13-08-1996T22:10:32');
    const testDateAsString = '13-08-1996 22:10:32';

    const pipe = new DatePipe();
    let apiService: ApiService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                { provide: ApiService, useClass: MockApiService },
                { provide: MainService, useValue: {} }
            ]
        });
        apiService = TestBed.get(ApiService);
    });

    // Date object test
    it('date (as Date object) will be properly transformed in DateFormat.Xshort format', () => {
        expect(pipe.transform(testDate, DateFormat.Xshort)).toBe('13-08-\'96');
    });
    it('date (as Date object) will be properly transformed in DateFormat.Short format', () => {
        expect(pipe.transform(testDate, DateFormat.Short)).toBe('13-08-1996');
    });
    it('date (as Date object) will be properly transformed in DateFormat.Pretty format', () => {
        expect(pipe.transform(testDate, DateFormat.Pretty)).toBe('13 augustus 1996');
    });
    it('date (as Date object) will be properly transformed in DateFormat.WithTime format', () => {
        expect(pipe.transform(testDate, DateFormat.WithTime)).toBe('13 augustus 1996 22:10:32');
    });
});

date.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';
import { ApiService } from '@app/services';
import { DateFormat } from '@app/enums';
import { DateSegments } from '@app/interfaces';

@Pipe({
    name: 'formatDate'
})
export class DatePipe implements PipeTransform {
    private date: DateSegments;

    constructor (
        private apiService: ApiService
    ) { }

    transform(date: Date | string, format: DateFormat = DateFormat.Pretty): string {
        if ( date instanceof Date ) {
            console.log(this.apiService);
            console.log(ApiService);
            date = this.apiService.transformDateToApi(date);
        }

..... (irrelevant code to this question)

我收到的错误是TypeError: Cannot read property 'transformDateToApi' of undefined

此时,我的试错策略又回到了将代码拼凑在一起的策略,这种策略并没有教给我任何东西。

【问题讨论】:

    标签: angular unit-testing karma-jasmine


    【解决方案1】:

    你做错了。

    管道非常简单,您不应该使用测试台来测试它们。相反,模拟您的服务并通过注入它来简单地创建管道。像这样的东西。

    import { TestBed } from '@angular/core/testing';
    import { DatePipe } from './date.pipe';
    import { DateFormat } from '@app/enums';
    import { ApiService } from '@app/services';
    import { MainService } from '@app/state';
    
    const apiServiceMock = {
      transformDateToApi(date: Date = new Date()): string {
        return '13-08-1996T22:10:32';
      }
    };
    
    describe('DatePipe', () => {
      const testDate = new Date('13-08-1996T22:10:32');
      const testDateAsString = '13-08-1996 22:10:32';
    
      let pipe: DatePipe;
      let apiService: ApiService;
    
      beforeEach(() => {
        TestBed.configureTestingModule({
          providers: [
            { provide: ApiService, useValue: apiServiceMock },
            { provide: MainService, useValue: {} }
          ]
        });
        apiService = TestBed.get(ApiService);
      });
    
      beforeEach(() => {
        pipe = new DatePipe(apiServiceMock as any);
      });
    
      // Date object test
      it('date (as Date object) will be properly transformed in DateFormat.Xshort format', () => {
        expect(pipe.transform(testDate, DateFormat.Xshort)).toBe('13-08-\'96');
      });
      it('date (as Date object) will be properly transformed in DateFormat.Short format', () => {
        expect(pipe.transform(testDate, DateFormat.Short)).toBe('13-08-1996');
      });
      it('date (as Date object) will be properly transformed in DateFormat.Pretty format', () => {
        expect(pipe.transform(testDate, DateFormat.Pretty)).toBe('13 augustus 1996');
      });
      it('date (as Date object) will be properly transformed in DateFormat.WithTime format', () => {
        expect(pipe.transform(testDate, DateFormat.WithTime)).toBe('13 augustus 1996 22:10:32');
      });
    });
    

    【讨论】:

    • 你不应该使用测试台来测试它们——那不是真的。不需要 TestBed 来测试它们的主要功能(这提供了独立的单元测试),但 @Pipe 注释和 DI 注释仍然未经测试。即使单元测试是绿色的,它也可能在生产或 e2e 中失败并出现模糊的错误。
    • 这就是我的意思,在 e2e 测试中测试它们。我正在为单元测试提出一个解决方案,它应该测试是否应用了业务规则。
    • 显然,为了避免任何问题,您也应该 write DOM tests。不知道,所以谢谢你让我看文档!
    • TestBed 在这里作为共同点,我只会进行 DOM 测试,除非管道很复杂并且除了transform 之外还有其他方法。管道类也可以注册为 TestBed 中的提供者,以便测试 DI。
    • 听说过单元测试中的隔离吗?如果您使用管道测试服务,您将完全打破这一点
    猜你喜欢
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 2020-02-11
    • 1970-01-01
    相关资源
    最近更新 更多