【问题标题】:read-only in importing function running unit test in node.js在 node.js 中导入运行单元测试的函数时只读
【发布时间】:2020-10-16 17:42:41
【问题描述】:

我尝试在 Jest 中模拟一个异步函数,我使用了文档中所示的 mockResolvedValue。但是我遇到了只读问题,我的模拟函数是从其他地方导入的,我的代码如下:

//index.js 
async function getUser(id) { 
    const user = await axios.get('./user') 
    return user
}
module.exports = {
    getUser
}
//index.spec.js
import { getUser } from './index.js';

it('test getUser', async () => {
    const expectedUser = [
        {
        id: '1',
        name: 'Alice',
        },
    ];

    getUser = jest.fn().mockResolvedValue(expectedResult); //error of getUser is read-only
    const result = await getUser();
    expect(result).toEqual(expectedResult);
})

【问题讨论】:

  • 那个测试似乎毫无意义,你似乎在试图模拟你应该测试的东西,所以你最终会测试模拟。你也没有jest.mock 任何东西,你应该看看例如jestjs.io/docs/en/manual-mocks.html.
  • 我正在尝试测试 getUser 函数,对吗?但我不想直接打服务器,这是我的目标。
  • 那么你需要模拟axios,而不是整个getUser。您也可以查看例如jest-mock-axios。但是 Axios 是一个你不拥有的接口,所以最好不要模拟它 - 考虑在它周围有一个外观,将你的代码与对 Axios 的更改隔离,然后模拟外观。或者,如果您有更高级别(例如端到端)的测试来告诉您请求是否停止工作,则可能根本不测试 getUser
  • 我有这个代码:async function getUser() { //what if there's multiple calls here? return something } 我不应该测试 getUser 的结果吗? axios 只是我用来从 api 获取结果的库。我现在真的很困惑我该怎么办..
  • 如果getUser 比您所展示的更复杂,那么它可能应该进行测试,您可以模拟 axios 或提取 axios 周围的外观并模拟它(因为,正如你所说,“axios 只是我使用的一个库” - 你不拥有它,以后可能想更改它)。我们无法为您做出这样的判断。

标签: javascript node.js axios jestjs


【解决方案1】:

如果你想测试getUser 函数,你应该模拟axios.get 方法及其返回值。使用jest.mock(moduleName, factory, options) 方法手动模拟axios模块。

例如

index.js:

const axios = require('axios');

async function getUser(id) {
  const user = await axios.get('./user');
  return user;
}
module.exports = {
  getUser,
};

index.spec.js:

import axios from 'axios';
import { getUser } from './';

jest.mock('axios', () => {
  return { get: jest.fn() };
});
describe('64385009', () => {
  it('test getUser', async () => {
    const expectedUser = [{ id: '1', name: 'Alice' }];
    axios.get.mockResolvedValueOnce(expectedUser);
    const result = await getUser();
    expect(result).toEqual(expectedUser);
    expect(axios.get).toBeCalledWith('./user');
  });
});

单元测试结果:

 PASS  src/stackoverflow/64385009/index.spec.js
  ✓ test getUser (6ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.js |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.27s, estimated 12s

【讨论】:

  • 是的,但是在 getUser 函数中,我在 axios 调用之后也有很少的函数来转换数据。如果我不使用 axios 怎么办?说这是一个 twitter 包装器库,我应该模拟包装器库吗?
  • @Ambrose 对于单元测试,您应该模拟每个副作用的方法/函数以使您的测试隔离。对于纯方法/函数,一般不需要mock,除非这些纯方法/函数的逻辑太复杂,只想得到一个简单的返回值。
猜你喜欢
  • 2012-02-14
  • 2012-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
  • 2018-06-24
  • 1970-01-01
  • 2019-04-18
相关资源
最近更新 更多