In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article shows you how to use the Mock simulation module and deal with component interaction in JavaScript. The content is concise and easy to understand, which will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.
We will learn how to test more complex components, including writing tests involving external API in Mock and easily simulating component interactions through Enzyme
The first attempt of Jest Mock
Our applications usually need to get data from an external API. When writing tests, the external API may fail for a variety of reasons. We want our tests to be reliable and independent, and the most common solution is Mock.
Rewrite TodoList components
First, let's modify the component so that it can get the data through API. Install axios:
Npm install axios
Then rewrite the TodoList component as follows:
/ / src/TodoList.js
Import React, {Component} from 'react'
Import axios from 'axios'
Import Task from'. / Task'
Const apiUrl = 'https://api.tuture.co';
Class ToDoList extends Component {
State = {
Tasks: []
}
ComponentDidMount () {
Return axios
.get (`${apiUrl} / tasks`)
.then ((tasksResponse) = > {
This.setState ({tasks: tasksResponse.data})
})
.catch ((error) = > console.log (error))
}
Render () {
Return (
{this.state.tasks.map ((task) = > (
))}
);
}
}
Export default ToDoList
TodoList has been transformed into a "smart component" that fetches data asynchronously through axios modules in componentDidMount lifecycle functions.
Write the mock file of axios module
Jest supports Mock of the entire module so that the component does not call the original module, but our preset Mock module. As officially recommended, we create the mocks directory and put the mock file in it. Create the Mock file axios.js for axios as follows:
/ / src/__mocks__/axios.js
'use strict'
Module.exports = {
Get: () = > {
Return Promise.resolve ({
Data: [
{
Id: 0
Name: 'Wash the dishes'
}
{
Id: 1
Name: 'Make the bed'
}
]
});
}
}
The axios module here provides a get function and returns a Promise containing preset false data.
Check the call of Mock module through the spyOn function
Let's start Mock. Get up! Open the test file for TodoList, first configure the Mock of the axios module through jest.mock (make sure that before import TodoList), and after Mock, you will use the Mock version of axios both in the test and in the component. Then create a test case to check that the Mock module is invoked correctly. The code is as follows:
/ / src/TodoList.test.js
Import React from 'react'
Import {shallow, mount} from 'enzyme'
Import axios from 'axios'
Jest.mock ('axios')
Import ToDoList from'. / ToDoList'
Describe ('ToDoList component', ()) = > {
/ /...
Describe ('when rendered', ()) = > {
It ('should fetch a list of tasks', ()) = > {
Const getSpy = jest.spyOn (axios, 'get')
Const toDoListInstance = shallow ()
Expect (getSpy) .toBeCalled ()
});
});
});
Testing whether a function in the module is called is actually difficult, but fortunately Jest provides us with complete support. First, through jest.spyOn, we can monitor the usage of a function, and then use the accompanying toBeCalled Matcher to determine whether the function is called or not. The overall code is very concise, but also maintains a good readability.
If you forget the meaning of Jest Matcher, it is recommended to read the first tutorial in this series.
Iterative TodoList component
An actual project will always iterate over and over again, including our TodoList components. For a to-do application, of course, the most important thing is to add a new to-do list.
Modify the TodoList component as follows:
/ / src/TodoList.js
/ /...
Class ToDoList extends Component {
State = {
Tasks: []
NewTask:''
}
ComponentDidMount () {
/ /...
.catch ((error) = > console.log (error))
}
AddATask = () = > {
Const {newTask, tasks} = this.state
If (newTask) {
Return axios
.post (`${apiUrl} / tasks`, {task: newTask})
.then ((taskResponse) = > {
Const newTasksArray = [... tasks]
NewTasksArray.push (taskResponse.data.task)
This.setState ({tasks: newTasksArray, newTask:''})
})
.catch ((error) = > console.log (error))
}
}
HandleInputChange = (event) = > {
This.setState ({newTask: event.target.value})
}
Render () {
Const {newTask} = this.state
Return (
ToDoList
Add a task
{this.state.tasks.map ((task) = > (
))}
);
}
}
Export default ToDoList
Since we made significant changes to the TodoList component, we need to update the snapshot:
Npm test-u
If you are not familiar with Jest snapshot testing, please refer back to the second tutorial in this series.
The updated snapshot file reflects the changes we just made:
/ / Jest Snapshot v1, https://goo.gl/fbAQLP
Exports [`ToDoList component when provided with an array of tasks should render correctly 1`] = `
ToDoList
Add a task
``
Simulate the interaction of React components in the test
In the TodoList iteration above, we used axios.post. This means that we need to extend axios's mock file:
/ / src/__mocks__/axios.js
'use strict'
Let currentId = 2
Module.exports = {
Get: () = > {
Return Promise.resolve ({
/ /...
]
});
}
Post: (url, data) = > {
Return Promise.resolve ({
Data: {
Task: {
Name: data.task
Id: currentId++
}
}
});
}
}
As you can see above, we added a currentId variable because we need to maintain the uniqueness of each task.
Let's start the test! The first thing we test is to check to see if the modified input value has changed our state:
We modify the app/components/TodoList.test.js as follows:
Import React from 'react'
Import {shallow} from 'enzyme'
Import ToDoList from'. / ToDoList'
Describe ('ToDoList component', ()) = > {
Describe ('when the value of its input is changed', ()) = > {
It ('its state should be changed', ()) = > {
Const toDoListInstance = shallow (
);
Const newTask = 'new task name'
Const taskInput = toDoListInstance.find ('input')
TaskInput.simulate ('change', {target: {value: newTask}})
Expect (toDoListInstance.state () .newTask) .toEqual (newTask)
});
});
});
The key point here is the call to the simulate [1] function. This is the function of ShallowWrapper that we have mentioned several times. We use it to simulate events. Its first argument is the type of event (since we use onChange in the input, we should use change here), and the second parameter is the mock event object (event).
To further illustrate, let's test whether the user clicks the button and sends the actual post request from our component. We modify the test code as follows:
Import React from 'react'
Import {shallow} from 'enzyme'
Import ToDoList from'. / ToDoList'
Import axios from 'axios'
Jest.mock ('axios')
Describe ('ToDoList component', ()) = > {
Describe ('when the button is clicked with the input filled out', ()) = > {
It ('a post request should be made', ()) = > {
Const toDoListInstance = shallow (
);
Const postSpy = jest.spyOn (axios, 'post')
Const newTask = 'new task name'
Const taskInput = toDoListInstance.find ('input')
TaskInput.simulate ('change', {target: {value: newTask}})
Const button = toDoListInstance.find ('button')
Button.simulate ('click')
Expect (postSpy) .toBeCalled ()
});
});
});
Thanks to our mock and simulate events, the test passed! Things are going to get a little tricky now. We will test whether the status is updated with our new task, and what is interesting is that the request is asynchronous, and we continue to modify the code as follows:
Import React from 'react'
Import {shallow} from 'enzyme'
Import ToDoList from'. / ToDoList'
Import axios from 'axios'
Jest.mock ('axios')
Describe ('ToDoList component', ()) = > {
Describe ('when the button is clicked with the input filled out, the new task should be added to the state', ()) = > {
It ('a post request should be made', ()) = > {
Const toDoListInstance = shallow (
);
Const postSpy = jest.spyOn (axios, 'post')
Const newTask = 'new task name'
Const taskInput = toDoListInstance.find ('input')
TaskInput.simulate ('change', {target: {value: newTask}})
Const button = toDoListInstance.find ('button')
Button.simulate ('click')
Const postPromise = postSpy.mock.results.pop () .value
Return postPromise.then ((postResponse) = > {
Const currentState = toDoListInstance.state ()
Expect (currentState.tasks.includes ((postResponse.data.task) .tobe (true)
})
});
});
});
As you can see above, postSpy.mock.results is an array of results sent by the post function, and by using it, we can get the returned promise, which we can get from the value property. Returning promise from a test is one way to ensure that Jest waits for the end of its asynchronous method execution.
Summary
In this article, we introduced the mock module and used it to forge API calls. Since no actual post request is made, our testing can be more reliable and faster. In addition, we simulate events throughout the React component. We checked to see if it produced the expected results, such as a request or state change for a component. To this end, we understand the concept of spy.
Try to test React Hooks
Hooks is an exciting addition to React, and there is no doubt that it can help us separate logic from templates. This makes the above logic more testable. Unfortunately, testing hooks is not that simple. In this article, we looked at how to handle it using react-hooks-testing-library [2].
We create the src/useModalManagement.js file as follows:
/ / src/useModalManagement.js
Import {useState} from 'react'
Function useModalManagement () {
Const [isModalOpened, setModalVisibility] = useState (false)
Function openModal () {
SetModalVisibility (true)
}
Function closeModal () {
SetModalVisibility (false)
}
Return {
IsModalOpened
OpenModal
CloseModal
}
}
Export default useModalManagement
The Hooks above makes it easy to manage schema state. Let's start testing if it doesn't raise any errors, let's create a useModalManagement.test.js
/ / src/useModalManagement.test.js
Import useModalManagement from'. / useModalManagement'
Describe ('The useModalManagement hook', ()) = > {
It ('should not throw an error', ()) = > {
UseModalManagement ()
});
});
We run the test and get the following results:
FAIL useModalManagement.test.js
The useModalManagement hook
✕ should not throw an error press ⌘ + ↩ to exit
Unfortunately, the above tests cannot be carried out properly. We can find out the cause by reading the error message:
Invalid Hooks call, Hooks can only be called inside the function body of a functional component.
Let the test pass
The React document [3] mentions that we can only call Hooks from functional components or other Hooks. We can use the enzyme library described earlier in this series to solve this problem, and with a bit of cleverness, we created testHook.js:
/ / src/testHook.js
Import React from 'react'
Import {shallow} from 'enzyme'
Function testHook (hook) {
Let output
Function HookWrapper () {
Output = hook ()
Return
}
Shallow ()
Return output
}
Export default testHook
Let's continue to iterate through useModalManagement.test.js with the following modifications:
/ / src/useModalManagement.test.js
Import useModalManagement from'. / useModalManagement'
Import testHook from'. / testHook'
Describe ('The useModalManagement hook', ()) = > {
It ('should not throw an error', ()) = > {
TestHook (useModalManagement)
});
});
We allow the test and get the following results:
PASS useModalManagement.test.js
The useModalManagement hook
✓ should not throw an error
Much better! However, the above solution is not very good and does not provide us with a comfortable way to further test Hooks. This is why we use react-hooks-testing-library [4].
The above is how to use Mock simulation module and handle component interaction in JavaScript. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.