嘲笑功能对象

时间:2020-05-06 19:42:35

标签: javascript unit-testing jestjs

我目前有一个用于与我的API api.js进行交互的对象:

export var Auth = (function () {
    var Login = async function(username, password) {
        //Async login code for interacting with the API
    };
    return {
        Login: Login
    }
});

此对象已导入另一个文件login.js中:

import * as API from './api';

export var LoginRequestHandler = function() {
   //processess user input, then calls:
   try {
       await API.Auth().Login(username, password);
   } catch(e) {
       throw new Error(e);
}

这是我开玩笑的测试:

import * as API from '../api';
import * as User from '../user';

jest.mock('../api');

const spy = jest.spyOn(API.Auth(), 'Login');
    User.LoginRequestHandler().then(() => {
        expect(spy).toHaveBeenLastCalledWith('theUsername', 'thePassword');
    }).catch(error => console.log(error));

这是我的模拟文件__mock__/api.js

export var Auth = (function () {
    var Login = async function(username, password) {
        return Promise.resolve(true);
    };
    return {
        Login: Login
    }
});

我通过theUsername中的thePassword检索了document.getElementId()LoginRequestHandler,并为上述测试创建了自己的DOM。

console.log(username)中添加LoginRequestHandler揭示了它正在被调用并能够获得正确的值。此外,在console.log(username)中添加API.Auth().Login也表明它也在获取正确的值。但是,当我查看测试日志时,发现:Number of calls: 0用于模拟功能,并且测试会导致错误。

我假设我试图监视错误的功能,并且无论如何我都可以解决此问题?

1 个答案:

答案 0 :(得分:0)

每次调用API.Auth()时,它将返回一个具有Login方法的新对象。因此,在测试用例中,在LoginRequestHandler函数中创建的对象和通过jest.spyOn(API.Auth(), 'Login')语句创建的对象是不同的。间谍只会添加到后面的间谍中。 Login函数中的LoginRequestHandler方法没有被监视。

因此,在这里,我将使用jest.mock()模拟api.js模块,而不将模拟对象放入__mocks__目录。例如

api.js

export var Auth = function () {
  var Login = async function (username, password) {};

  return {
    Login: Login,
  };
};

user.js

import * as API from './api';

export var LoginRequestHandler = async function () {
  const username = 'theUsername';
  const password = 'thePassword';
  try {
    await API.Auth().Login(username, password);
  } catch (e) {
    throw new Error(e);
  }
};

user.test.js

import * as API from './api';
import * as User from './user';

jest.mock('./api', () => {
  const auth = { Login: jest.fn() };
  return {
    Auth: jest.fn(() => auth),
  };
});

describe('61643983', () => {
  afterEach(() => {
    jest.clearAllMocks();
  });
  it('should login', () => {
    expect.assertions(2);

    return User.LoginRequestHandler().then(() => {
      expect(API.Auth).toBeCalledTimes(1);
      expect(API.Auth().Login).toHaveBeenLastCalledWith('theUsername', 'thePassword');
    });
  });

  it('should throw error', () => {
    expect.assertions(4);
    const mError = new Error('user not found');
    API.Auth().Login.mockRejectedValueOnce(mError);

    return User.LoginRequestHandler().catch((e) => {
      expect(API.Auth).toBeCalled();
      expect(API.Auth().Login).toHaveBeenLastCalledWith('theUsername', 'thePassword');
      expect(e).toBeInstanceOf(Error);
      expect(e.message).toMatch(/user not found/);
    });
  });
});

具有100%覆盖率的单元测试结果:

 PASS  stackoverflow/61643983/user.test.js (11.507s)
  61643983
    ✓ should login (5ms)
    ✓ should throw error (3ms)

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

源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61643983