react导入组件_模拟导入的React组件和各种助手

react导入组件

I know the documentation on Jest provides all the information needed when it comes to mocking imports of a test React components. Yet I sometimes find myself crawling through various blogs, or even Github snippets examples! So I figured out some self-explanatory examples could ease others’ life!

我知道Jest的文档提供了模拟测试React组件的导入时所需的所有信息。 但是我有时发现自己在各种博客甚至Github片段示例中爬行! 所以我想出了一些不言自明的例子可以减轻别人的生活!

Testing a React component can requires to control its imports, usually by mocking them. Several strategies are possible for this. Here is how I usually handle things, depending on the context: likelihood of re-using the mocking across the project, type of mocked import (functional component, default exported function, simple export, …).

测试React组件可能需要控制其导入,通常是通过模拟它们来进行。 为此可能有几种策略。 根据上下文,这是我通常的处理方式:在项目中重复使用模拟的可能性,模拟导入的类型(功能组件,默认导出的函数,简单的导出等)。

单次手动模拟 (Single time manual mock)

React组件 (React Component)

I remember I once had to easily test some stuffs in a React component that were wrapped inside an other React component. This wrapper depended on multiple factors in order to render the children. Something like this:

我记得我曾经不得不轻松地测试React组件中包装在其他React组件中的某些东西。 该包装程序取决于多个因素以呈现子级。 像这样:

import Layout from './Layout' const ComponentToTest = ({name}) => (
<Layout>
<div>{`my name is ${name}`}</div>
</Layout>)

Here, Layout return its children prop under very specific conditions (think of an API call for example), that we aim not to assert in our test. Mocking the Layout here so that it returns children no matter what is a good way to only focus on what happens inside the <Layout>! (I know, really simple component here ^^) .

在这里,Layout在非常特定的条件下返回其子项prop(例如,想想API调用),我们不打算在测试中声明该条件。 在这里模拟布局,以便它返回children不管什么是仅关注<Layout>内部发生的事情的好方法! (我知道,这里的组件非常简单^^)。

Just mock the component at the top of your test file like this:

只需模拟测试文件顶部的组件,如下所示:

jest.mock('./Layout', () => ({children}) => <>{children}</>);

Now Jest will happily replace any Layout usage with the mock.

现在,Jest将很高兴用该模拟替换任何Layout用法。

ES模块 (ES Modules)

When it comes to an ES Module, mocking also applies. You may use different strategies, given if you mock a default export or if it is a named import: export default niceModule VS export {niceModule} .

对于ES模块,模拟也适用。 您可以使用不同的策略,例如模拟默认的导出或命名的导入: export default niceModule VS export {niceModule}

A common example is when you want to mock some axios methods. Your component is like this:

一个常见的示例是当您要模拟一些axios方法时。 您的组件是这样的:

import React, {useEffect} from 'react';
import axios from 'axios';
const MyComponent = () => { useEffect(() => {
axios.get('/api/data').then(() => ...)
},[]) return (
...
)
}

You will want to save the cost of making a real API requests, and you will want to control what this axios call does. A way to do this in your test file could be, since here the import is a default one:

您将希望节省发出真实API请求的成本,并且将需要控制此axios调用的功能。 在您的测试文件中可以这样做,因为在这里导入是默认的:

import axios from 'axios'; // import axios prior to mocking it!
jest.mock('axios'); // extra work on some steps (not required)
axios.get.mockImplementation(() => Promise.resolve({status:200}));// NOTE: if you define the implementation at the top of the file,
// make sure to mockClear it before each test instance or you could // experience side effects when the whole file is tested.

Later on in your tests, you can make sure that the axios call have been called, and have return whatever you set into the mockImplementation.

稍后在您的测试中,您可以确保axios调用已被调用,并已将您设置的所有内容返回给模拟Implementation。

test('axios is returning a 200 status', async () => {
const wrapper = mount(<MyComponent/>);
expect(axios.get).toHaveBeenCalledTimes(1);
await expect(axios.get).resolves.toBe({status:200});
})

Note: You can always mock a default export like this, prior to writing your tests:

注意:在编写测试之前,您始终可以模拟这样的默认导出:

jest.mock('./helpers/defaultExportedHelper', () => ({
__esModule: true,
default: jest.fn(() => ({})),
specificMethod : jest.fn(() => [])
}));// __esModule: true, is mandatory if you mock both default and named // exports in the same mock.// invocation of this module as a default within the file will
// return {}.
// invocation of {specificMethod} from this module will return [].

Last, when it comes to test a single import of a file, I personally use the spyOn method provided by Jest. Say the file import a method like this:

最后,在测试文件的一次导入时,我个人使用了Jest提供的spyOn方法。 说文件导入方法是这样的:

import {getCookies} from './helpers/cookiesMethods';

That is something you can easily mock in your test file:

您可以在测试文件中轻松模拟出这一点:

const spyCookiesGet = jest.spyOn(require('./helpers/cookiesMethods'),'getCookies');spyCookiesGet.mockImplementation((cookieName) =>`${cookieName}_value`);  
// in case you want to return something from an attempt of getting cookies, and not an undefined value! spyCookiesGet.mockReturnValue('something');
// alternatively, you can return something regardless the input

you can then expect any attempt of the tested using the getCookies method to have a value returned, which is a concatenation of the asked key like so:

然后,您可以预期使用getCookies方法进行的任何测试尝试都会返回一个值,该值是所要求的键的串联,如下所示:

getCookie('token'); // will return 'token_value' in the test

全局对象 (Global Objects)

Last but not least, in case you need to mock something like the window, or even a process.env … you can do this:

最后但并非最不重要的一点是,如果您需要模拟诸如window甚至是process.env类的东西,可以执行以下操作:

test('test something in a particular context of process' , () => {
process.env.API_KEY = 'wrongAPIKey'; // the rest of the test will use this API_KEY replacement
// anywhere needed during its execution (api call or whatever).})

and for window (location for ex, but any global object would behave similarly):

对于窗口(对于ex,位置,但是任何全局对象的行为都类似):

test('test something in a particular context of window.location.href' , () => {
Object.defineProperty(window, 'location', {
value: {
href: 'fakeurl'
}
});// now you can test anything that would normally use the href of the // window, replacing undefined value with the one you provided.
})

All of these are convenient, easy to implement, for single case of having to mock the behaviour (a browser, a cookie/session storage, etc…). But when you have to at various places on such modules or components, you may want to have them out of the box, without rewriting the mock pattern everywhere needed.

所有这些都非常方便,易于实现,仅需模拟行为的一种情况(浏览器,Cookie /会话存储等)。 但是,当您必须在此类模块或组件的各个位置上使用时,可能希望将它们开箱即用,而无需在任何需要的地方重写模拟模式。

通过__mocks__文件夹模拟 (Mock via __mocks__ folder)

All what have been said previously does apply in this section, but in terms of reusability and cleanliness of code, you want to move one step further. Jest covers your back, with __mocks__ folders!

前面所说的所有内容都适用于本节,但是就代码的可重用性和简洁性而言,您想进一步向前迈进。 __mocks____mocks__文件夹__mocks__您的后背!

Jest understands that having a sibling __mocks__ folder next to a file in the folder structure of your app is a way for you, whenever you decide it, to replace a normal import of such file with its mocked version instead. The organisation of files is like this (React components or ES Modules work the same).

Jest知道,在您应用的文件夹结构中的文件旁边有一个同级__mocks__文件夹,是您随时决定用其模拟版本替换此类文件的常规导入的一种方法。 文件的组织是这样的(React组件或ES模块的工作原理相同)。

/helpers
|---cookiesMethods.js
|---/__mocks__
| └--cookiesMethods.js

ES模块 (ES Modules)

You can mock the cookiesMethods file by typing jest.mock('./helpers/cookiesMethods') at the top of your test file. The mocked file will be imported instead of the normal version. Don’t forget to export named and/or default objects the same way you are doing in the normal version.

您可以通过在测试文件顶部键入jest.mock('./helpers/cookiesMethods')来模拟cookiesMethods文件。 模拟文件将被导入,而不是普通版本。 不要忘记以与普通版本相同的方式导出命名和/或默认对象。

// ./helpers/__mocks__/cookiesMethods.js
// let's write two functions that will exported as a named and as a // default
const getCookies = (name) => {
return `${name}_value`;
}const listAllCookies = () => ['cookies1','cookies2'];export {getCookies};
export default listAllCookies;

React组件 (React Component)

Of course, this applies for a React component as well. Just render a normal component, the way you like it, and put it in a sibling __mocks__ folder next to the actual component you are making a mock of.

当然,这也适用于React组件。 只需按照您喜欢的方式渲染普通组件,然后将其放在要模拟的实际组件旁边的同级__mocks__文件夹中即可。

Here is a situation:

这是一种情况:

import ComponentB from './componentB'const ComponentA = () => (
<>
<ComponentB />
// other jsx things that you want to test
</>
)

Here you are testing a ComponentA that normally imports a ComponentB , which according to you, has to be mocked. Just create a mocked ComponentB file in a __mocks__ folder next the ComponentB, like so:

在这里,您正在测试ComponentA ,该ComponentA通常会导入ComponentB ,根据您的说法,该ComponentB必须被模拟。 只需在ComponentB旁边的__mocks__文件夹中创建一个__mocks__ ComponentB文件,如下所示:

/components
|---componentA.js
|---componentB.js
|---/__mocks__
| └--componentB.js

and in the test file of ComponentA , just do this

并在ComponentA的测试文件中,只需执行此操作

import ComponentA from './componentA'
jest.mock('./ComponentB')

now the call to ComponentB will be replaced with its mock!

现在,对ComponentB的调用将被其模拟代替!

只需使用Jest设置即可! (Just use the Jest setup!)

Using mock folder allows you to fine tune whether you want to call the actual file or its mocked version. But in some case, you know that you will want a mocked version, no matter what. That’s basically what jest.setup.js (unless you configured a different name in your configuration) does.

使用模拟文件夹允许您微调是否要调用实际文件或其模拟版本。 但是在某些情况下,您知道无论如何都将需要一个模拟版本。 这基本上就是jest.setup.js (除非您在配置中配置了其他名称)。

it can be as simple as, for ex:

它可以很简单,例如:

// jest.setup.jswindow.scrollTo = jest.fn()

That’s right, just providing a mock function for this window.scrollTo(x-coord, y-coord) that you use everywhere in your code! Now you are safe to have this method being called anywhere in your test, and you can even monitor it.

没错,只需为此window.scrollTo(x-coord, y-coord)提供一个模拟函数,即可在代码中的任何地方使用它! 现在您可以放心地在测试中的任何地方调用此方法,甚至可以对其进行监视。

This is my very first post on medium, and I get that through documentation and other really good articles about the topic, this one is maybe un-needed. Personally I feel like having more than one example for understanding something is always welcomed. Time to write nice tests now!

这是我关于媒体的第一篇文章,我可以通过有关该主题的文档和其他非常好的文章来了解这一点,也许这是不需要的。 就个人而言,我总是喜欢有一个以上的例子来理解某些东西。 现在该写不错的测试了!

翻译自: https://medium.com/swlh/mock-imported-react-components-and-various-helpers-fea4240be7eb

react导入组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值