Имитация объекта функции с помощью шутки - PullRequest
1 голос
/ 06 мая 2020

Сейчас у меня есть объект, который используется для взаимодействия с моим 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 голосов
/ 07 мая 2020

Каждый раз, когда вы вызываете 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...