как смоделировать конструктор в атрибуте стороннего субтитра, используя шутку - PullRequest
0 голосов
/ 22 января 2019

У нас есть простое экспресс-приложение. Мы используем winston в качестве третьей стороны, чтобы иметь возможность правильно обрабатывать журналы.

const express = require('express');
const app = express();
const { createLogger, transports } = require('winston');

const port = process.env.PORT || 5000;
const logger = createLogger({ transports: [ new transports.Console()] });

const { catchAll } = require('./routes/catchall');

app.get('*', catchAll);

app.listen(port, () => logger.log({ level: 'info', message: `server listening on port ${port}!` }));

В нашем модульном тестировании мы хотели бы проверить, что createLogger был вызван с правильными аргументами.

Сначала мы попытались использовать jest.mock('winston), но шутка жалуется, что TypeError: transports.Console is not a constructor.

Затем мы попытались вручную смоделировать пакет, используя:

let { createLogger, transports } = require('winston');

const consoleClass = class Console{};
jest.doMock('winston', () => {
  return {
    createLogger: jest.fn(),
    transports: {
      Console: consoleClass
    }
  }
});

describe('logger', () => {
  it('should create proper logger', () => {
    expect(createLogger).lastCalledWith({ transports: [ new transports.Console()] })
  });
});

Ошибка с консолью исчезла. Но тогда наш тест не проходит с:

logger › should create proper logger

expect(jest.fn())[.not].lastCalledWith()

jest.fn() value must be a mock function or spy.
Received:
  function: [Function anonymous]

  39 | describe('logger', () => {
  40 |   it('should create proper logger', () => {
> 41 |     expect(createLogger).lastCalledWith({ transports: [ new transports.Console()] })
     |                          ^
  42 |   });
  43 | });
  44 |

  at Object.lastCalledWith (tests/app.spec.js:41:26)

Мы пытались добавить после doMock

createLogger.mockImplementation(() => {});

Но жаловался, что TypeError: createLogger.mockImplementation is not a function

Как мы можем заменить атрибуты transports и createLogger?

Нам нужно иметь возможность смоделировать реализацию createLogger, чтобы затем в другом тесте утверждать, что app.listen был вызван с logger.log и соответствующими параметрами.

1 Ответ

0 голосов
/ 22 января 2019

Попробуйте следующее:

const mockCreateLogger = jest.fn().mockImplementation(() => {
  log: jest.fn()
});
const mockConsole = jest.fn().mockImplementation(() => () => {});
jest.mock('winston', () => ({
  createLogger: mockCreateLogger, // name must start with mock prefix
  transports: {
    Console: mockConsole // name must start with mock prefix
  }
}));

// here import the file you are testing after the mocks

describe('logger', () => {
  it('should create proper logger', () => {
    expect(mockCreateLogger).toHaveBeenCalledWith({ transports: expect.anything() })
  });
});

p.s. для правильного написания здесь своих юнит-тестов, вы должны также смоделировать express, чтобы работать с проверенным app, а не импортировать «настоящий» экспресс

...