#reactjs #jestjs #axios #enzyme #axios-mock-adapter
#reactjs #jestjs #axios #фермент #axios-макет-адаптер
Вопрос:
Я использую axios-mock-adapter
для создания макета моего API, он работает корректно, но в одном макете он возвращает ошибку 404, и я не могу найти, почему.
Здесь есть песочница с тестом, вы можете увидеть, когда мы запустим тест, вторая проверка не удалась, потому что axios POST
вызов не был макетом. Я попытался удалить часть заголовка, но в песочнице произошел сбой, когда я запустил test.
Макет API (тестовая часть):
import axios from "axios";
import MockAdapter from 'axios-mock-adapter';
import Utils from "../Utils/Utils";
// Global variable for post request with axios
global.users_post = axios.create({
baseURL: "http://localhost:5000/api/",
headers: {'Content-Type': 'application/json'}
});
/* Mockup API */
var userMock = new MockAdapter(users_post);
const user_resp_full = {
data: {
first_name: "Test",
last_name: "Test",
email: "test@gmail.com",
address: "Test",
zipcode: 1010,
city: "Test",
admin: false
}
}
const testAPI = () => {
userMock
.onPost("users", user_resp_full, Utils.getAuth())
.reply(200, {data: {status: "success"}});
}
test("something", async () => {
let tree = shallow(<UserManage type="create" uuid="" />);
testAPI();
await flushPromises();
// Some test
tree.find("#confirm-create").simulate("click");
await flushPromises();
// Error 404, mock isn't trigger
})
Я уже проверил, данные те же, то же самое для конечной точки, но, похоже, это неправильно издевается.
Вызов Axios в классе:
function (fields) {
users_post.post("users", fields, Utils.getAuth())
.then(resp => {
let data = resp.data;
// Do something
})
.catch(resp => {
let data = resp.response.data;
// Display error
});
}
На данный момент в моем тесте Jest он возвращает ошибку 404, поэтому он не имитировал мой endpoint API (другие работы).
Utils.getAuth()
Функция возвращает заголовок с токеном аутентификации.
Отправка данных
Это касается содержимого отправляемых данных (первое — перед тестовым вызовом с макетом, второе — в тестируемой функции, а журнал данных — это данные, отправляемые в api):
console.log src/tests/UserManage.test.js:222
POST USER 2
{"first_name":"Test","last_name":"Test","email":"test@gmail.com","address":"Test","zipcode":1010,"city":"Test","admin":false}
console.log src/Components/Users/UserManage.js:152
POST USER
console.log src/Components/Users/UserManage.js:153
{"first_name":"Test","last_name":"Test","email":"test@gmail.com","address":"Test","zipcode":1010,"city":"Test","admin":false}
Обновить
Эта ошибка возникает только тогда, когда я использую POST
запрос с подобным заголовком:
axios.post("http://localhost/api/user/update", {name: "Test"}, {headers: {"Authorization": "Bearer token")}});
Я вижу на тестовой странице axios-mock-adapter github, что в конечном итоге мы должны поставить headers
тест без метки перед:
{headers: {Autorization: "Bearer token"}}
стать {Autorization: "Bearer token"}
Но, к сожалению, это работает не лучше, чем у меня.
Решение
С ответом Мэтта Карлотты и его codesandbox я модифицирую свой с помощью 2 примеров исправленной проблемы:
- Проверка
POST
макета запроса с использованием axios* - Проверка
POST
макета запроса с использованием экземпляра axios*
* С axios-mock-adapter
Комментарии:
1. Возможно, это совершенно не связано, но в вашей функции testApi ничего не возвращается. На самом деле я не вижу смысла в функции testApi, что, если вы поместите свой userMock.onPost() … непосредственно в свой тест («что-то»)?
2. Спасибо за ваш комментарий, я тестирую это, но, к сожалению, не работает. Я использую эту функцию для другого макета другой конечной точки, и они работают.
3. вы пробовали добавлять начальную косую черту к вашему onPost вызову ‘/users’? во всех примерах показаны ведущие косые черты, github.com/ctimmerm/axios-mock-adapter
4. @N3SS4H Да, но я использую конфигурацию axios, у которой в baseUrl есть ..базовый URL, например
http://localhost:5000/
, и я тестирую его, но он не работает.
Ответ №1:
Отлично, второй раунд.
- Ваша
flushPromises
функция не решаетсяpromises
должным образом, когда для ответа на этоpromise
требуется некоторое время. Обходной путь заключается в том, чтобыreturn
promise
вставитьawait
перед ним в.test.js
файл. Поскольку мы используемawait
наpromise
,await flushPromises()
не требуется. - Кроме того, включение
headers
вonPost
издевательскую функцию приведет к тому, что функция выдаст ошибку. Поскольку вы просто издеваетесь над этим запросом (а на самом деле не тестируете его интеграцию), вам не нужно их включать. Однако, поскольку вы все равно уже используете пользовательскуюaxios
конфигурацию, вы можете просто включитьheaders
вaxiosConfig.js
файл. Смотрите рабочий пример вашего codesandbox для получения дополнительной информации.
Как показано в Unit Testing
codesandbox ниже, если вы попытаетесь использовать метод await flushPromises()
on deleteUserDataOverTime
, произойдет сбой. Сбой, потому что он не разрешил promise
. Для устранения этого promise
требуется некоторое время, и оно не обрабатывается должным образом.
Кроме того, из-за asynchronous
характера тестов вы не должны включать unit
и integration
тесты в один и тот же тестовый файл. Поскольку тесты asynchronous
, вызывающие mockAxios.reset()
or mockAxios.restore()
по тому же поддельному запросу или тому же поддельному экземпляру — для выполнения любых дополнительных реальных или поддельных вызовов API — могут и будут непреднамеренно влиять на все вызовы API (опять же, это асинхронные, а не синхронные тесты).
Рабочий пример модульного тестирования API: https://codesandbox.io/s/6z36z6pzyr (поддельный API — включает GET
, PUT
POST
и DELETE
)
Рабочий пример интеграционного тестирования API: https://codesandbox.io/s/7z93xnm206 (реальный API — включает только GET
, но функциональность должна оставаться неизменной для PUT
, POST
и DELETE
)
Рабочий пример вашего codesandbox: https://codesandbox.io/s/526pj28n1n
Комментарии:
1. Ваш ответ на самом деле не помогает мне в решении моей проблемы, вы описываете тест с
GET
запросом, но никто не сообщает оPOST
запросе с заголовком, который может быть ошибкой. Однако я создам тест, который можно воспроизвести.2. Да, это имеет значение, потому что мой
GET
запрос (тот же, что и в вашем тесте) в моем тесте работает отлично, но это было не так с моимPOST
запросом, который все не удался. Итак, я ищу, почемуPOST
запрос не удался, но я собираюсь создать тест в изолированной среде с этим.3. Я добавил ссылку на изолированную среду.
4. Пожалуйста, прочитайте внимательно: тест реализации API (он же
Unit Test
) будет имитироватьrequest
,side effect
иresult
. Тест интеграции API (он жеEnd to End Test
) фактически протестируетrequest
,side effect
иresult
от клиента к API. Я также обновил свой ответ выше, чтобы подчеркнуть различия.5. Уверен, что я разобрался с вашей проблемой. Смотрите обновленный ответ выше.
Ответ №2:
Хорошо, это было сложно. Проблема в пакете axios-mock-adapter. Для этого требуется экземпляр axios, использующий .create()
метод. Смотрите здесь: создание экземпляра
В вашем App.js, используйте:
import axios from "axios";
const instance = axios.create();
instance.post("http://localhost/api/user/update", {name: "Test"}, {headers: {"Authorization": "Bearer token")}});
Однако в тестах ничего не нужно менять.
Я получил подсказку из тестов axios-mock-adapter.
Примером такого является: post test
Комментарии:
1. Как и на github
axios-mock-adapter
, я отправляю вам CodeSandbox , обновленный вашим решением, но это не работает. Кроме того, в моей проблеме уже используется экземпляр axios с пользовательской конфигурацией и тоже не работает.