jest.clearAllMocks(); не удаляет фиктивную реализацию в пределах afterEach
У меня есть файл с именем src/layouts/index.js
// ./src/layouts/index.js
const importAll = (r) =>
r.keys().reduce(
(acc, key) => ({
...acc,
[key.replace(/^\.\/(.*).json$/, '$1')]: r(key)
}),
{}
);
module.exports = importAll(require.context('./', true, /\.json$/));
Он использует веб-пакет require.context
поэтому я пытаюсь издеваться над jest.mock.
У меня есть другой файл... скажем, файл util.js
//./src/util.js
import layouts from '../layouts';
export const getLayout(name) {
return layouts[name];
}
в моем тесте я пытаюсь очистить макеты после каждого теста
//./src/util.test.js
describe('my test suite', () => {
afterEach(() => {
jest.clearAllMocks();
})
test('test number one', () => {
jest.mock('./layouts', () => ({
layout1 : { a : 1 },
layout2 : { b: 2 },
}));
assert.equals(getLayout('layout1').a, 1);
assert.equals(getLayout('layout2').b, 2);
});
test('test number two', () => {
assert.equals(getLayout('layout1').a, 1);
assert.equals(getLayout('layout2').b, 2);
});
});
Я ожидаю, что первый тест пройдет, а второй провалится... потому что макет должен был быть очищен.
Насколько я понимаю, параллельная модель выполнения шутки, тесты внутри каждого набора запускаются последовательно, поэтому вы должны иметь возможность издеваться над каждым отдельным тестом.
К вашему сведению, насмешливая документация и API крайне неясны и слишком сложны ИМХО.
jest.clearAllMocks
не удаляет фиктивные реализации по замыслу — попробуйте jest.resetAllMocks
Вот соответствующие документы:
Все еще не работает с resetAllMocks:
Пример включает:
https://repl.it/@CharlieHoover/SorrowfulBackSandboxes-2
Кроме того, что это очень двусмысленно. Почему функция под названием clearAllMocks не очищает моки... Назовите функцию resetMockState
или что-то более описательное. clearAllMocks
означает, что макеты очищаются.
@rickhanlonii мой вопрос еще не решен. Я хочу удалить мокасины.
Ах, да, похоже, что resetAllMocks не сбрасывает фиктивные _module factory_, а только реализации, установленные mockImplementation. Если вы хотите опубликовать то, что вы хотите сделать, в stackoverflow, я могу помочь вам сделать то, что вы хотите, но это не похоже на то, что здесь есть ошибка.
Почему функция под названием clearAllMocks не очищает макеты
Я думаю, что путаница в том, что «макет» в «clearAllMocks» не относится к фиктивным реализациям, он относится к фиктивным объектам Jest. Таким образом, эта функция означает «очистить все фиктивные объекты шутки», то есть вызвать .mockClear для всех фиктивных объектов (т.е. очистить вызовы)
@rickhanlonii
omg, так что # 1 кажется, что «очистить» и «сбросить» используются противоположно их логическому значению.
Кроме того, совершенно ясно, что он пытается сделать; удалите фиктивную реализацию, и вы говорите, что нет способа сделать это или ррр.....?????
Это должно быть вновь открыто
+1
+1
+1
У меня похожая проблема: когда я издеваюсь над реализацией в предыдущем случае, это будет затронуто в следующем случае.
+1
тоже борюсь с этим!
+1, пожалуйста, обновите документы, чтобы объяснить, как УДАЛИТЬ макет/шпион
+1, пожалуйста, обновите документы, чтобы объяснить, как УДАЛИТЬ макет/шпион
Разве не для этого предназначен mockRestore? https://jestjs.io/docs/en/mock-function-api#mockfnmockrestore
Я думаю, что конфигурация по умолчанию должна включать:
{
restoreMocks: true,
clearMocks: true,
resetMocks: true
}
Шокирует то, что поведение по умолчанию — рвота между тестами. Не могли бы вы оставить мои тесты изолированными по умолчанию? Затем [надеющееся меньшинство], которое хочет распространить состояние на несколько тестов, может сделать это, подписавшись.
`
описать('тест', () => {
перед каждым (() => {
const WelcomeService = require('./../SOME_MODULE')
WelcomeServiceSpyOfMessage = jest.spyOn(
Добро пожаловатьСервис,
'сообщение', // какая-то функция, над которой я издевался
)
const IsUserAuthentic = требуется ('./../SOME_MODULE')
IsUserAuthenticSpyOnIsUserAuthentic = jest.spyOn(
IsUserAuthentic,
'isUserAuthentic' // какая-то функция, над которой я издевался
)
app = require('../src/server') // мой сервер Express
})
afterEach(() => {
jest.restoreAllMocks()
})
it('1. Mock implementation', async () => {
const mockedMessage = faker.lorem.sentence()
WelcomeServiceSpyOfMessage.mockImplementation(() => mockedMessage)
IsUserAuthenticSpyOnIsUserAuthentic.mockImplementation(() => {
console.log('>>> MOCKED MW 1')
return true
})
const result = await request(app)
.get('/api')
expect(result.statusCode).toBe(200)
expect(result.body).toHaveProperty('message', mockedMessage)
})
it('2. After restored implementation', async () => {
IsUserAuthenticSpyOnIsUserAuthentic.mockImplementation(() => {
console.log('>>> MOCKED MW 2')
return true
})
const result = await request(app)
.get('/api')
expect(result.statusCode).toBe(200)
expect(result.body).toHaveProperty('message', 'hello world')
})
})
`
Вывод:
console.log тест/routes.test.js:36
насмехается над мв 1
console.log тест/routes.test.js:36
насмехается над мв 1
Для обоих тестов вызывается одна и та же имитированная версия функции. Хотя я восстановил все макеты в вызове равно вызывается один и тот же макет. Подскажите, пожалуйста, где я пропустил.
Спасибо
+1 🥂
+1
+1
Мне кажется, что очистка макетов после каждого теста должна быть поведением по умолчанию.
+1
Мне кажется, что очистка макетов после каждого теста должна быть поведением по умолчанию.
+1
функции, имитированные с помощью .spyOn()
могут быть восстановлены: jest.spyOn(object, method).mockImplementation(mockFunction)
.
Я согласен с тем, что макеты должны автоматически очищаться между тестами.
+1
+1
Есть ли решение этой проблемы? +1
Столкнулся с такой же проблемой!
У меня такая же проблема, но я не нашел решения в официальной документации jest.
Поэтому я делаю не изящное решение ниже. Затем используйте его везде, где нужно удалить макет.
// jestUtil.js
const mockArr = [];
export function doAMock(moduleName, cb = null) {
if (!mockArr.includes(moduleName)) {
mockArr.push(moduleName);
}
if (cb) {
jest.doMock(moduleName, cb);
} else {
jest.doMock(moduleName);
}
}
export function removeAllMock() {
mockArr.forEach(m => {
jest.dontMock(m);
});
mockArr.length = 0;
}
// usage
// other.test.js
import * as jsUtil from './jestUtil.js';
jsUtil.doAMock('module');
jsUtil.removeAllMock();
IMO, это очень запутанное название API, и оно заслуживает того, чтобы его переименовали.
IMO, это очень запутанное название API, и оно заслуживает того, чтобы его переименовали.
да, полностью согласен - но мне все еще интересно, возможно ли это в настоящее время - не говоря уже об именах. Если да, то как?
Это действительно должно быть исправлено. Нет причин, по которым один модульный тест должен влиять на другой. Кто-нибудь нашел жизнеспособный обходной путь? Действительно странный функционал.
РЕДАКТИРОВАТЬ: Решение @damien-roche для обновления jest.config.js сработало хорошо, плюс добавлен мой вызов Class.mockImplementation в хуке beforeEach:
beforeEach(() => {
CommunicationApi.mockImplementation(() => {
return {
getMessagePosition() {
return new Promise(resolve => {
resolve({
ok: true,
Id: '123',
json: function () {
return null
}
});
});
},
getMessageOptions() {
return Promise.resolve(expectedMessageOptions);
},
};
});
getters = createGetters(baseGetters);
wrapper = createWrapper(getters, actions)
});
Кто-нибудь когда-нибудь собирается что-то делать с этим? Я также сталкиваюсь с той же проблемой.
Это все еще проблема
У меня тоже проблема с этим.
Для тех, кто сталкивается с этим, я установил флаг командной строки --restoreMocks
который также можно установить в jest.config.js
:
restoreMocks: true,
По умолчанию для моих тестов, чтобы макеты всегда восстанавливались после запуска теста. Вот ссылка на документацию: https://jestjs.io/docs/en/configuration#restoremocks -boolean
Согласитесь, это странное значение по умолчанию, которое сохраняет состояние между модульными тестами.
@ewhauser у меня не
вы уверены, что это работает для вас?
@pkyeck Кажется, это зависит от среды. Если я запускаю набор тестов в своей локальной среде, он очищает все макеты, но когда я запускаю его внутри контейнера докеров, он, похоже, не сбрасывает их должным образом.
Я только что наткнулся на mockRestore
, который работает, если вы используете spyOn
.
Делает все, что делает mockFn.mockReset(), а также восстанавливает исходную (не издевательскую) реализацию.
Это полезно, когда вы хотите имитировать функции в определенных тестовых случаях и восстановить исходную реализацию в других.
Имейте в виду, что mockFn.mockRestore работает только тогда, когда макет был создан с помощью jest.spyOn. Таким образом, вы должны сами позаботиться о восстановлении при ручном назначении jest.fn().
Параметр конфигурации restoreMocks доступен для автоматического восстановления макетов между тестами.
https://jestjs.io/docs/en/mock-function-api#mockfnmockrestore
Я нашел это полезным. Вызывайте эту функцию с ожиданием каждый раз сразу после того, как ожидается вызов фальшивой fn.
flushAllPromises() {
return new Promise(resolve => setImmediate(resolve));
}
Это должно заставить работать последний вызов YourClass.yourFunction.mockResolvedValue() в выполняющемся тестовом примере вместо того, чтобы полагаться на разрешенное значение последнего выполненного модульного теста.
Ой, подождите, я вижу, что происходит. Вы меняете фиктивную реализацию, но не меняете никакие другие параметры, которые сделают запуск теста уникальным, поэтому Jest использует предыдущий кэшированный ответ. Если вы измените какую-то небольшую часть состояния, которая сделает тест уникальным, он будет использовать измененную реализацию. Вот почему обещание сбрасывания было предложено выше.
Эти API необходимо переименовать. Соглашаться на плохое название из-за инерции, по меньшей мере, непрофессионально.
Ребята, это полнейшая некомпетентность. Я использую Jest не по своему выбору, я использую его, потому что вы сделали его популярным. Этот вопрос был открыт с октября 2018 года. Вы просто оказываете медвежью услугу сообществу, которому пытаетесь служить..? Соберись.
Эти API необходимо переименовать. Соглашаться на плохое название из-за инерции, по меньшей мере, непрофессионально.
Я согласен, что это «непрофессионально», я и все остальные, кто поддерживал Jest за последние ~ 2 года, делали это в свободное время, поэтому не профессионально. Но я бы не стал говорить о «некомпетентности».
В любом случае, пожалуйста, не используйте трекер ошибок для комментариев не по теме или (успешных или неудачных) оскорблений; такие комментарии будут скрыты или о них будет сообщено.
Для меня jest.restoreAllMocks();
помог окончательно очистить шпиона на шутку
Самый полезный комментарий
К вашему сведению, насмешливая документация и API крайне неясны и слишком сложны ИМХО.