Просто немного об этом курсе Удеми ... это не самый лучший инструмент обучения. Инструктор подходит к тестированию, используя data attributes
, которые не нужны для тестирования jest
и enzyme
(они также заполняют DOM
неиспользуемыми атрибутами).
Кроме того, ее опыт работы с кодом находится на начальном уровне, и она делает довольно много ошибок и делает странный выбор кода. Тем не менее, узнайте, что вы можете из него, и начните изучать тесты, созданные теми, кто поддерживает популярные пакеты npm (большинство хорошо документированных и популярных пакетов будут содержать тесты, которые научат вас более практическому подходу unit
и integration
тестирование).
Во всяком случае, я отвлекся, у вас есть два варианта для тестирования container
:
export
class
/ pure function
, shallow
или mount
оберните его и обновите его поддельными подпорками (очень легко, меньше головной боли и более распространено)
- Оберните ваш компонент в
<Provider>
в формате dupx и <MemoryRouter>
в router-router-dom, а затем mount
it (может стать очень сложным, поскольку требует полуглубокого понимания: энзима и того, как он интерпретирует DOM когда компонент смонтирован, последовательность действий / редуктора Redux, как создавать фиктивные реализации и / или фиктивные файлы и как правильно обрабатывать действия promise
)
Рабочие примеры (перейдите на вкладку Tests
для запуска тестов; найдите .tests.js
в каталогах, указанных ниже):
Примечание: Codesandbox в настоящее время имеет некоторые ограничения тестирования, как указано ниже, поэтому, пожалуйста, настройте его для вашего локального проекта.
Containers / Dashboard / __ tests __ / UnconnectedDashboard.test.js (вы можете просто mount
обернуть этот неподключенный компонент, чтобы утверждать его глубоко вложенные дочерние узлы)
import { Dashboard } from "../index.js";
/*
codesandbox doesn't currently support mocking, so it's making real
calls to the API; as a result, the lifecycle methods have been
disabled to prevent this, and that's why I'm manually calling
componentDidMount.
*/
const getCurrentProfile = jest.fn();
const fakeUser = {
id: 1,
name: "Leanne Graham",
username: "Bret",
email: "Sincere@april.biz",
address: {
street: "Kulas Light",
suite: "Apt. 556",
city: "Gwenborough",
zipcode: "92998-3874",
geo: {
lat: "-37.3159",
lng: "81.1496"
}
},
phone: "1-770-736-8031 x56442",
website: "hildegard.org",
company: {
name: "Romaguera-Crona",
catchPhrase: "Multi-layered client-server neural-net",
bs: "harness real-time e-markets"
}
};
const initialProps = {
getCurrentProfile,
currentUser: {},
isLoading: true
};
describe("Unconnected Dashboard Component", () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<Dashboard {...initialProps} />);
wrapper.instance().componentDidMount();
});
afterEach(() => wrapper.unmount());
it("initially renders a spinnner", () => {
expect(getCurrentProfile).toHaveBeenCalled();
expect(wrapper.find("Spinner")).toHaveLength(1);
});
it("displays the current user", () => {
wrapper.setProps({ currentUser: fakeUser, isLoading: false });
expect(getCurrentProfile).toHaveBeenCalled();
expect(wrapper.find("DisplayUser")).toHaveLength(1);
});
it("displays a signup message if no users exist", () => {
wrapper.setProps({ isLoading: false });
expect(getCurrentProfile).toHaveBeenCalled();
expect(wrapper.find("DisplaySignUp")).toHaveLength(1);
});
});
контейнеры / Панель управления / __ тесты __ / ConnectedDashboard.test.js
import Dashboard from "../index";
// import { getCurrentProfile } from "../../../actions/profileActions";
import * as types from "../../../types";
/*
codesandbox doesn't currently support mocking, so it's making real
calls to the API; however, actions like getCurrentProfile, should be
mocked as shown below -- in your case, you wouldn't need to use
a promise, but instead just mock the "guessedWord" action and return
store.dispatch({ ... })
*/
const fakeUser = {
id: 1,
name: "Leanne Graham",
username: "Bret",
email: "Sincere@april.biz",
address: {
street: "Kulas Light",
suite: "Apt. 556",
city: "Gwenborough",
zipcode: "92998-3874",
geo: {
lat: "-37.3159",
lng: "81.1496"
}
},
phone: "1-770-736-8031 x56442",
website: "hildegard.org",
company: {
name: "Romaguera-Crona",
catchPhrase: "Multi-layered client-server neural-net",
bs: "harness real-time e-markets"
}
};
const flushPromises = () => new Promise(resolve => setImmediate(resolve));
describe("Connected Dashboard Component", () => {
let store;
let wrapper;
beforeEach(() => {
store = createStoreFactory();
wrapper = mount(
<Provider store={store}>
<MemoryRouter>
<Dashboard />
</MemoryRouter>
</Provider>
);
});
afterEach(() => wrapper.unmount());
it("initially displays a spinner", () => {
expect(wrapper.find("Spinner")).toHaveLength(1);
});
it("displays the current user after a successful API call", async () => {
/*
getCurrentProfile.mockImplementationOnce(() => new Promise(resolve => {
resolve(
store.dispatch({
type: types.SET_SIGNEDIN_USER,
payload: fakeUser
})
);
});
await flushPromises();
wrapper.update();
expect(wrapper.find("DisplayUser")).toHaveLength(1);
*/
store.dispatch({
type: types.SET_SIGNEDIN_USER,
payload: fakeUser
});
wrapper.update();
expect(wrapper.find("DisplayUser")).toHaveLength(1);
});
it("displays a signup message if no users exist", async () => {
/*
getCurrentProfile.mockImplementationOnce(() => new Promise((resolve,reject) => {
reject(
store.dispatch({
type: types.FAILED_SIGNEDIN_USER
})
);
});
await flushPromises();
wrapper.update();
expect(wrapper.find("DisplaySignUp")).toHaveLength(1);
*/
store.dispatch({
type: types.FAILED_SIGNEDIN_USER
});
wrapper.update();
expect(wrapper.find("DisplaySignUp")).toHaveLength(1);
});
});