Проблема в том, что код, который вы пытаетесь протестировать, является асинхронным, а написанные вами тесты - нет.
Когда вы запускаете тесты, обратный вызов onload
для FileReader
невыполняется во время выполнения соответствующего теста.Вместо этого он вызывается после выполнения теста.Фактически, поскольку у вас есть утверждение:
console.log("Content is valid: ", contentIsValid)
внутри метода importFile
, вы должны увидеть в консоли сообщение, подобное этому:
Невозможно войти в систему после тестовсделано.Вы забыли дождаться чего-то асинхронного в своем тесте?
Вам нужно сделать свои тесты асинхронными , чтобы они ожидали выполнения обратного вызова onload
.К сожалению, ваш код сложно протестировать как есть, потому что у вас нет возможности узнать, когда был выполнен обратный вызов onload
, поэтому в этом тесте также сложно ждать до этого момента.
В одну сторонуЧтобы решить эту проблему, нужно заключить ваш асинхронный код в Promise и вернуть его, чтобы мы могли подождать, пока обещание не будет выполнено.При таком подходе ваш importFile
будет выглядеть примерно так:
export function importFile(e, importScenarios, importDevices) {
const file = e.target.files[0]
const fileReader = new FileReader()
fileReader.readAsText(file)
return new Promise((resolve, reject) => {
fileReader.onload = () => { // File loaded
const fileContent = JSON.parse(fileReader.result)
const ajv = new Ajv({allErrors: true})
const validate = ajv.compile(schema)
const contentIsValid = validate(fileContent)
if (contentIsValid) {
importScenarios(fileContent.scenarios)
importDevices(fileContent.devices)
resolve()
} else {
reject(new InvalidFileError("This file doesn't match the schema"))
}
}
});
}
Затем вы можете протестировать этот метод, вернув Обещание в тесте (так что Jest знает, что он должен ждать, пока обещание не будетразрешено или отклонено):
let importScenarios = jest.fn()
let importDevices = jest.fn()
test("Does it work with a file matching the schema?", () => {
expect.assertions(2);
file = new Blob(correctTestContent, { type: "application/json" })
e.target.files.push(file)
return FileManager.importFile(e, importScenarios, importDevices).then(() => {
expect(importScenarios).toHaveBeenCalledTimes(1);
expect(importDevices).toHaveBeenCalledTimes(1);
});
});
test('Does it work with a file not matching the schema??', () => {
expect.assertions(1);
file = new Blob(incorrectTestContent, { type: "application/json" })
e.target.files.push(file)
return FileManager.importFile(e, importScenarios, importDevices).catch((e) => {
expect(e).toBeInstanceOf(InvalidFileError);
});
});
Обратите внимание, что я переопределил переменные importScenarios
и importDevices
, чтобы они были фиктивными функциями , и мы можем проверить, вызваны ли они.Также обратите внимание на использование expect.assertions
для проверки того, что вызывается определенное количество утверждений.
Наконец, учтите, что если вы переопределите свой importFile
, чтобы он возвращал обещание, вы, скорее всего,должны изменить места, где вы называете это, чтобы рассматривать случай отказа.Где у вас есть:
try {
FileManager.importFile(e, importScenarios, importDevices)
} catch(e) {
// Some treatment of your exception
}
вам понадобится:
FileManager.importFile(e, importScenarios, importDevices).catch(e => {
// Some treatment of your exception
})