首页 > 解决方案 > 具有异步方法的节点服务的 Jest 单元测试

问题描述

我得到以下错误。为什么我收到undefined来自服务的响应?我为提供模拟实现做错了什么吗?

在此处输入图像描述

服务:

export class SaveDataService{
    async save() : Promise<any> {
        try{
            return this.someFunction()
        } catch(ex){
            throw new Error('some error occured')
        }
    }

    async someFunction() : Promise<any>{
        const response = {
            "file" : "<htm><body>This is sample response</body></html>"
        }
        return Promise.resolve(response);
    }
}

测试/规格文件:

import { SaveDataService } from "./save-data.service";

jest.mock('./save-data.service')

describe('tests for SaveDataService', () => {

    it('when save method is called and success result is returned', async () => {
        let mockSaveDataServiceSomeFunction = jest.fn().mockImplementation(() => {
            return Promise.resolve('Success Result')
        }); 
        SaveDataService.prototype.someFunction = mockSaveDataServiceSomeFunction;

        let spy = jest.spyOn(SaveDataService.prototype, 'someFunction');

        let service = new SaveDataService();
        let data = await service.save()
        expect(data).toEqual('Success Result')
        expect(spy).toHaveBeenCalled()
    })

    it('when save method is called and error is returned', async () => {
        let mockSaveDataServiceSomeFunction = jest.fn().mockImplementation(() => {
            throw new Error('ERROR')
        }); 
        SaveDataService.prototype.someFunction = mockSaveDataServiceSomeFunction;

        let spy = jest.spyOn(SaveDataService.prototype, 'save');

        let service = new SaveDataService();
        service.save()
        expect(spy).toThrowError('ERROR')
    })
})

标签: node.jstypescriptunit-testingjestjsjasmine

解决方案


模拟替换依赖项。您设置对依赖对象调用的期望,设置它应该为您执行所需测试的确切返回值,和/或抛出哪些异常,以便您可以测试异常处理代码。

在这种情况下,您通过调用来模拟 save-data.servicejest.mock('./save-data.service')。这样你的班级可能看起来像这样:

async save() : Promise<any>  {
  // do nothing or undefined
}

async someFunction() : Promise<any>  {
  // do nothing or undefined
}

因此,您必须自己实现主体,以期待您希望方法/函数为您做什么。你只是在嘲笑someFunction

...

let mockSaveDataServiceSomeFunction = jest.fn().mockImplementation(() => {
    return Promise.resolve('Success Result')
}); 

SaveDataService.prototype.someFunction = mockSaveDataServiceSomeFunction;

...

因此,当您调用该save()方法时,您仍然一无所获/未定义。

您正在覆盖我认为您的测试可能没有用的服务的整个行为。但是您可以通过以下方式修复您的测试:

import { SaveDataService } from "./save-data.service";

jest.mock('./save-data.service');

describe('tests for SaveDataService', () => {
  beforeEach(() => {
    SaveDataService.mockClear();
  });

  it('when save method is called and success result is returned', async () => {
    const spy = jest
      .spyOn(SaveDataService.prototype, 'save')
      .mockImplementation(async () => Promise.resolve('Success Result'));

    const service = new SaveDataService();
    const data = await service.save();

    expect(data).toEqual('Success Result');
    expect(spy).toHaveBeenCalled();
  })

  it('when save method is called and error is returned', async () => {
    const spy = jest
      .spyOn(SaveDataService.prototype, 'save')
      .mockImplementation(() => {
        throw new Error('ERROR');
      });

    const service = new SaveDataService();
    expect(service.save).toThrowError('ERROR');
    expect(spy).toHaveBeenCalled();
  });
});

推荐阅读