vue-jest测试用例
笑话简介 (Introduction to Jest)
Jest is a library for testing JavaScript code.
Jest是用于测试JavaScript代码的库。
It’s an open source project maintained by Facebook, and it’s especially well suited for React code testing, although not limited to that: it can test any JavaScript code. Its strengths are:
这是Facebook维护的一个开源项目,它特别适合于React代码测试,但不仅限于此:它可以测试任何JavaScript代码。 它的优势是:
- it’s fast 它很快
it can perform snapshot testing
它可以执行快照测试
- it’s opinionated, and provides everything out of the box without requiring you to make choices 固执己见,并提供所有现成的内容,而无需您做出选择
Jest is a tool very similar to Mocha, although they have differences:
Jest是与Mocha非常相似的工具,尽管它们之间存在差异:
- Mocha is less opinionated, while Jest has a certain set of conventions 摩卡(Mocha)固执己见,而杰斯特(Jest)有一些约定
- Mocha requires more configuration, while Jest works usually out of the box, thanks to being opinionated Mocha需要更多配置,而Jest通常开箱即用,这要归功于他们的自以为是
- Mocha is older and more established, with more tooling integrations 摩卡(Mocha)更老,更成熟,具有更多的工具集成
In my opinion the biggest feature of Jest is it’s an out of the box solution that works without having to interact with other testing libraries to perform its job.
在我看来,Jest的最大特点是它是一种即用型解决方案,无需与其他测试库进行交互即可执行其工作。
安装 (Installation)
Jest is automatically installed in create-react-app
, so if you use that, you don’t need to install Jest.
Jest会自动安装在create-react-app
,因此,如果您使用它,则无需安装Jest。
Jest can be installed in any other project using Yarn:
Jest可以使用Yarn安装在任何其他项目中:
yarn add --dev jest
or npm:
或npm :
npm install --save-dev jest
notice how we instruct both to put Jest in the devDependencies
part of the package.json
file, so that it will only be installed in the development environment and not in production.
注意,我们如何指示两者将Jest放在package.json
文件的devDependencies
部分中,以便仅将其安装在开发环境中,而不能在生产环境中安装。
Add this line to the scripts part of your package.json
file:
将此行添加到package.json
文件的脚本部分:
{
"scripts": {
"test": "jest"
}
}
so that tests can be run using yarn test
or npm run test
.
这样可以使用yarn test
或npm run test
。
Alternatively, you can install Jest globally:
或者,您可以全局安装Jest:
yarn global add jest
and run all your tests using the jest
command line tool.
并使用jest
命令行工具运行所有测试。
创建第一个Jest测试 (Create the first Jest test)
Projects created with create-react-app
have Jest installed and preconfigured out of the box, but adding Jest to any project is as easy as typing
使用create-react-app
项目已经安装并预先配置了Jest,但是将Jest添加到任何项目就像键入一样容易
yarn add --dev jest
Add to your package.json
this line:
package.json
下行添加到package.json
:
{
"scripts": {
"test": "jest"
}
}
and run your tests by executing yarn test
in your shell.
并通过在外壳中执行yarn test
来运行测试。
Now, you don’t have any tests here, so nothing is going to be executed:
现在,您在这里没有任何测试,因此将不执行任何操作:
Let’s create the first test. Open a math.js
file and type a couple functions that we’ll later test:
让我们创建第一个测试。 打开math.js
文件,并输入几个函数,稍后我们将对其进行测试:
const sum = (a, b) => a + b
const mul = (a, b) => a * b
const sub = (a, b) => a - b
const div = (a, b) => a / b
module.exports = { sum, mul, sub, div }
Now create a math.test.js
file, in the same folder, and there we’ll use Jest to test the functions defined in math.js
:
现在,在同一文件夹中创建一个math.test.js
文件,在这里我们将使用Jest测试math.js
定义的功能:
const { sum, mul, sub, div } = require('./math')
test('Adding 1 + 1 equals 2', () => {
expect(sum(1, 1)).toBe(2)
})
test('Multiplying 1 * 1 equals 1', () => {
expect(mul(1, 1)).toBe(1)
})
test('Subtracting 1 - 1 equals 0', () => {
expect(sub(1, 1)).toBe(0)
})
test('Dividing 1 / 1 equals 1', () => {
expect(div(1, 1)).toBe(1)
})
Running yarn test
results in Jest being run on all the test files it finds, and returning us the end result:
在Jest上运行的yarn test
结果将在它发现的所有测试文件上运行,并向我们返回最终结果:
用VS Code运行Jest (Run Jest with VS Code)
Visual Studio Code is a great editor for JavaScript development. The Jest extension offers a top notch integration for our tests.
Visual Studio Code是JavaScript开发的出色编辑器。 Jest扩展为我们的测试提供了一流的集成。
Once you install it, it will automatically detect if you have installed Jest in your devDependencies and run the tests. You can also invoke the tests manually by selecting the Jest: Start Runner command. It will run the tests and stay in watch mode to re-run them whenever you change one of the files that have a test (or a test file):
安装后,它将自动检测是否已在devDependencies中安装了Jest并运行测试。 您也可以通过选择Jest:Start Runner命令来手动调用测试。 每当您更改具有测试的文件之一(或测试文件)时,它将运行测试并停留在监视模式下以重新运行它们:
匹配器 (Matchers)
In the previous article I used toBe()
as the only matcher:
在上一篇文章中,我使用toBe()
作为唯一的匹配器 :
test('Adding 1 + 1 equals 2', () => {
expect(sum(1, 1)).toBe(2)
})
A matcher is a method that lets you test values.
匹配器是一种允许您测试值的方法。
Most commonly used matchers, comparing the value of the result of expect()
with the value passed in as argument, are:
最常用的匹配器,将Expect expect()
结果的值与作为参数传递的值进行比较,它们是:
toBe
compares strict equality, using===
toBe
使用===
比较严格相等toEqual
compares the values of two variables. If it’s an object or array, it checks the equality of all the properties or elementstoEqual
比较两个变量的值。 如果是对象或数组,则检查所有属性或元素的相等性toBeNull
is true when passing a null value传递null值时,
toBeNull
为truetoBeDefined
is true when passing a defined value (opposite to the above)传递定义的值时,
toBeDefined
为true(与上述相反)toBeUndefined
is true when passing an undefined value传递未定义的值时,
toBeUndefined
为truetoBeCloseTo
is used to compare floating values, avoiding rounding errorstoBeCloseTo
用于比较浮动值,避免舍入错误toBeTruthy
true if the value is considered true (like anif
does)toBeTruthy
如果该值被视为true,则为true(如if
那样)toBeFalsy
true if the value is considered false (like anif
does)toBeFalsy
如果该值被视为false,则为true(如if
那样)toBeGreaterThan
true if the result of expect() is higher than the argument如果
toBeGreaterThan
()的结果高于参数,toBeGreaterThan
truetoBeGreaterThanOrEqual
true if the result of expect() is equal to the argument, or higher than the argumenttoBeGreaterThanOrEqual
如果toBeGreaterThanOrEqual
()的结果等于参数,或者高于参数,toBeGreaterThanOrEqual
truetoBeLessThan
true if the result of expect() is lower than the argument如果
toBeLessThan
()的结果低于参数,toBeLessThan
truetoBeLessThanOrEqual
true if the result of expect() is equal to the argument, or lower than the argumenttoBeLessThanOrEqual
如果toBeLessThanOrEqual
()的结果等于参数,或者小于参数,toBeLessThanOrEqual
truetoMatch
is used to compare strings with regular expression pattern matchingtoMatch
用于比较具有正则表达式模式匹配的字符串toContain
is used in arrays, true if the expected array contains the argument in its elements settoContain
用于数组中,如果期望的数组在其元素集中包含参数,则为truetoHaveLength(number)
: checks the length of an arraytoHaveLength(number)
:检查数组的长度toHaveProperty(key, value)
: checks if an object has a property, and optionally checks its valuetoHaveProperty(key, value)
:检查对象是否具有属性,并可选地检查其值toThrow
checks if a function you pass throws an exception (in general) or a specific exceptiontoThrow
检查您传递的函数是否抛出异常(通常)或特定异常toBeInstanceOf()
: checks if an object is an instance of a classtoBeInstanceOf()
:检查对象是否是类的实例
All those matchers can be negated using .not.
inside the statement, for example:
可以使用.not.
否定所有这些匹配器.not.
在语句中,例如:
test('Adding 1 + 1 does not equal 3', () => {
expect(sum(1, 1)).not.toBe(3)
})
For use with promises, you can use .resolves
and .rejects
:
与promise一起使用时,可以使用.resolves
和.rejects
:
expect(Promise.resolve('lemon')).resolves.toBe('lemon')
expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus')
建立 (Setup)
Before running your tests you will want to perform some initialization.
在运行测试之前,您将需要执行一些初始化。
To do something once before all the tests run, use the beforeAll()
function:
要在所有测试运行之前执行一次操作,请使用beforeAll()
函数:
beforeAll(() => {
//do something
})
To perform something before each test runs, use beforeEach()
:
要在每次测试运行之前执行某些操作,请使用beforeEach()
:
beforeEach(() => {
//do something
})
拆除 (Teardown)
Just as you can do with setup, you can also perform something after each test runs:
就像您可以进行设置一样,您还可以在每次测试运行后执行一些操作:
afterEach(() => {
//do something
})
and after all tests end:
在所有测试结束后:
afterAll(() => {
//do something
})
使用describe()进行组测试 (Group tests using describe())
You can create groups of tests, in a single file, that isolate the setup and teardown functions:
您可以在单个文件中创建测试组,以隔离设置和拆卸功能:
describe('first set', () => {
beforeEach(() => {
//do something
})
afterAll(() => {
//do something
})
test(/*...*/)
test(/*...*/)
})
describe('second set', () => {
beforeEach(() => {
//do something
})
beforeAll(() => {
//do something
})
test(/*...*/)
test(/*...*/)
})
测试异步代码 (Testing asynchronous code)
Asynchronous code in modern JavaScript can have basically 2 forms: callbacks and promises. On top of promises we can use async/await.
现代JavaScript中的异步代码基本上可以有两种形式:回调和承诺。 除了承诺,我们还可以使用async / await。
回呼 (Callbacks)
You can’t have a test in a callback, because Jest won’t execute it - the execution of the test file ends before the callback is called. To fix this, pass a parameter to the test function, which you can conveniently call done
. Jest will wait until you call done()
before ending that test:
您不能在回调中进行测试,因为Jest不会执行测试-测试文件的执行在调用回调之前结束。 要解决此问题,请将参数传递给测试函数,您可以方便地调用done
。 Jest将等到您调用完done()
之后再结束该测试:
//uppercase.js
function uppercase(str, callback) {
callback(str.toUpperCase())
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require('./src/uppercase')
test(`uppercase 'test' to equal 'TEST'`, (done) => {
uppercase('test', (str) => {
expect(str).toBe('TEST')
done()
}
})
承诺 (Promises)
With functions that return promises, we return a promise from the test:
使用返回承诺的函数,我们从测试中返回承诺 :
//uppercase.js
const uppercase = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject('Empty string')
return
}
resolve(str.toUpperCase())
})
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require('./uppercase')
test(`uppercase 'test' to equal 'TEST'`, () => {
return uppercase('test').then(str => {
expect(str).toBe('TEST')
})
})
Promises that are rejected can be tested using .catch()
:
可以使用.catch()
测试被拒绝的承诺:
//uppercase.js
const uppercase = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject('Empty string')
return
}
resolve(str.toUpperCase())
})
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require('./uppercase')
test(`uppercase 'test' to equal 'TEST'`, () => {
return uppercase('').catch(e => {
expect(e).toMatch('Empty string')
})
})
异步/等待 (Async/await)
To test functions that return promises we can also use async/await, which makes the syntax very straightforward and simple:
为了测试返回promise的函数,我们还可以使用async / await,这使得语法非常简单明了:
//uppercase.test.js
const uppercase = require('./uppercase')
test(`uppercase 'test' to equal 'TEST'`, async () => {
const str = await uppercase('test')
expect(str).toBe('TEST')
})
模拟 (Mocking)
In testing, mocking allows you to test functionality that depends on:
在测试中, 模拟使您可以测试依赖于以下功能的功能:
Database
数据库
Network requests
网络请求
access to Files
访问文件
any External system
任何外部系统
so that:
以便:
your tests run faster, giving a quick turnaround time during development
您的测试运行速度更快 ,从而在开发过程中缩短了周转时间
your tests are independent of network conditions, or the state of the database
您的测试与网络条件或数据库状态无关
your tests do not pollute any data storage because they do not touch the database
您的测试不会污染任何数据存储,因为它们不会影响数据库
- any change done in a test does not change the state for subsequent tests, and re-running the test suite should start from a known and reproducible starting point 测试中所做的任何更改都不会更改后续测试的状态,并且重新运行测试套件应从已知且可复制的起点开始
- you don’t have to worry about rate limiting on API calls and network requests 您不必担心API调用和网络请求的速率限制
Mocking is useful when you want to avoid side effects (e.g. writing to a database) or you want to skip slow portions of code (like network access), and also avoids implications with running your tests multiple times (e.g. imagine a function that sends an email or calls a rate-limited API).
当您想要避免副作用(例如,写入数据库)或希望跳过代码的慢速部分(例如,网络访问),并且还可以避免多次运行测试(例如,假设某个函数发送一个电子邮件或调用受速率限制的API)。
Even more important, if you are writing a Unit Test, you should test the functionality of a function in isolation, not with all its baggage of things it touches.
更重要的是,如果您正在编写单元测试 ,则应该隔离测试功能的功能,而不是对其涉及的所有事物进行测试。
Using mocks, you can inspect if a module function has been called and which parameters were used, with:
使用模拟,您可以通过以下方法检查是否已调用模块函数以及使用了哪些参数:
expect().toHaveBeenCalled()
: check if a spied function has been calledexpect().toHaveBeenCalled()
:检查是否已调用间谍函数expect().toHaveBeenCalledTimes()
: count how many times a spied function has been calledexpect().toHaveBeenCalledTimes()
:计算一个间谍函数被调用了多少次expect().toHaveBeenCalledWith()
: check if the function has been called with a specific set of parametersexpect().toHaveBeenCalledWith()
:检查是否已使用一组特定的参数调用了该函数expect().toHaveBeenLastCalledWith()
: check the parameters of the last time the function has been invokedexpect().toHaveBeenLastCalledWith()
:检查上次调用该函数的参数
间谍软件包而不会影响功能代码 (Spy packages without affecting the functions code)
When you import a package, you can tell Jest to “spy” on the execution of a particular function, using spyOn()
, without affecting how that method works.
导入包时,可以使用spyOn()
告诉Jest对特定功能的执行进行“间谍”,而不会影响该方法的工作方式。
Example:
例:
const mathjs = require('mathjs')
test(`The mathjs log function`, () => {
const spy = jest.spyOn(mathjs, 'log')
const result = mathjs.log(10000, 10)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
模拟整个包裹 (Mock an entire package)
Jest provides a convenient way to mock an entire package. Create a __mocks__
folder in the project root, and in this folder create one JavaScript file for each of your packages.
Jest提供了模拟整个程序包的便捷方法。 在项目根目录中创建一个__mocks__
文件夹,并在此文件夹中为每个包创建一个JavaScript文件。
Say you import mathjs
. Create a __mocks__/mathjs.js
file in your project root, and add this content:
假设您导入mathjs
。 在项目根目录中创建__mocks__/mathjs.js
文件,并添加以下内容:
module.exports = {
log: jest.fn(() => 'test')
}
This will mock the log() function of the package. Add as many functions as you want to mock:
这将模拟包的log()函数。 添加任意数量的要模拟的函数:
const mathjs = require('mathjs')
test(`The mathjs log function`, () => {
const result = mathjs.log(10000, 10)
expect(result).toBe('test')
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
模拟一个功能 (Mock a single function)
You can mock a single function using jest.fn()
:
您可以使用jest.fn()
模拟单个函数:
const mathjs = require('mathjs')
mathjs.log = jest.fn(() => 'test')
test(`The mathjs log function`, () => {
const result = mathjs.log(10000, 10)
expect(result).toBe('test')
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
You can also use jest.fn().mockReturnValue('test')
to create a simple mock that does nothing except returning a value.
您还可以使用jest.fn().mockReturnValue('test')
创建一个简单的模拟程序,除了返回值外,该模拟程序不执行任何操作。
预先建立的模拟 (Pre-built mocks)
You can find pre-made mocks for popular libraries. For example this package https://github.com/jefflau/jest-fetch-mock allows you to mock fetch()
calls, and provide sample return values without interacting with the actual server in your tests.
您可以找到流行库的预制模型。 例如,此程序包https://github.com/jefflau/jest-fetch-mock允许您模拟fetch()
调用,并提供示例返回值,而无需与测试中的实际服务器进行交互。
快照测试 (Snapshot testing)
Snapshot testing is a pretty cool feature offered by Jest. It can memorize how your UI components are rendered, and compare it to the current test, raising an error if there’s a mismatch.
快照测试是Jest提供的一项很酷的功能。 它可以记住UI组件的呈现方式,并将其与当前测试进行比较,如果不匹配,则会引发错误。
This is a simple test on the App component of a simple create-react-app
application (make sure you install react-test-renderer
):
这是对一个简单的create-react-app
应用程序的App组件的简单测试(确保安装了react-test-renderer
):
import React from 'react'
import App from './App'
import renderer from 'react-test-renderer'
it('renders correctly', () => {
const tree = renderer.create(<App />).toJSON()
expect(tree).toMatchSnapshot()
})
the first time you run this test, Jest saves the snapshot to the __snapshots__
folder. Here’s what App.test.js.snap contains:
第一次运行此测试时,Jest将快照保存到__snapshots__
文件夹中。 这是App.test.js.snap包含的内容:
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div
className="App"
>
<header
className="App-header"
>
<img
alt="logo"
className="App-logo"
src="logo.svg"
/>
<h1
className="App-title"
>
Welcome to React
</h1>
</header>
<p
className="App-intro"
>
To get started, edit
<code>
src/App.js
</code>
and save to reload.
</p>
</div>
`
As you see it’s the code that the App component renders, nothing more.
如您所见,这是App组件呈现的代码,仅此而已。
The next time the test compares the output of <App />
to this. If App changes, you get an error:
下次测试将<App />
的输出与此进行比较时。 如果应用程序发生更改,则会出现错误:
When using yarn test
in create-react-app
you are in watch mode, and from there you can press w
and show more options:
在create-react-app
使用yarn test
,您处于观看模式 ,然后可以按w
并显示更多选项:
Watch Usage
› Press u to update failing snapshots.
› Press p to filter by a filename regex pattern.
› Press t to filter by a test name regex pattern.
› Press q to quit watch mode.
› Press Enter to trigger a test run.
If your change is intended, pressing u
will update the failing snapshots, and make the test pass.
如果您打算进行更改,请按u
将更新失败的快照,并通过测试。
You can also update the snapshot by running jest -u
(or jest --updateSnapshot
) outside of watch mode.
您还可以通过在监视模式之外运行jest -u
(或jest --updateSnapshot
)来更新快照。
vue-jest测试用例