msb msw
When we talk about testing our applications, one of the main issues we need to keep in mind is how we should deal with the requests that our application makes to the server, as virtually every application interacts with requests in some way.
当我们谈论测试应用程序时,我们需要牢记的主要问题之一是如何处理应用程序对服务器的请求,因为几乎每个应用程序都以某种方式与请求交互。
To many, this process may sound familiar and even simple. If you already have experience with this part, perhaps the first thing that comes to mind is to simply create a mock with jest
, something like this (axios):
对于许多人来说,这个过程听起来很熟悉,甚至很简单。 如果您已经有这部分的经验,那么可能想到的第一件事就是简单地创建一个带有jest
的模拟,像这样(axios):
However, it may not be the best solution or at least the most robust one, what do I mean by that?
但是,它可能不是最佳解决方案,或者至少不是最强大的解决方案,那是什么意思?
When we mock some library as axios, we are inferring that the request was made correctly, that is, that if our request required sending certain headers, for example, these were sent correctly when perhaps they were not and, since our test is probably not focused on making sure those headers were sent, we run the risk of letting a mistake go by.
当我们将某个库模拟为axios时,我们推断该请求是正确发出的,也就是说,如果我们的请求要求发送某些标头,例如,这些标头在可能不是正确的时候正确发送了,因为我们的测试可能不是专注于确保发送了这些标头,我们冒犯错误的风险。
On the other hand, this is not the only complexity that can be presented to us with this approach, as many know, another of the needs that the form outlined above requires, is to repeat code so that each test can have the implementation and response that we need. This can result in very large files that are difficult to maintain.
另一方面,这不是用这种方法可以给我们带来的唯一复杂性,众所周知,上面概述的表单所要求的另一个需求是重复代码,以便每个测试都可以具有实现和响应。我们需要的。 这会导致难以维护的非常大的文件。
替代方案……msw.js (The alternative… msw.js)
msw stands for Mock Service Worker
, a tool that takes care of intercepting all requests made at your network level. Let’s explain a little more in detail what this is all about.
msw代表Mock Service Worker
,该工具负责拦截在您的网络级别发出的所有请求。 让我们更详细地说明这是什么。
The basic idea of msw is to create a fake server that intercepts all requests and handles them like a real server. This implies that you can implement this tool as a set of “databases” either from json files to “seed” the data, or “constructors” like fakerJS and then create drivers (similar to the express API) and interact with that simulated database. This allows us to test our application under conditions very similar to those in production, either for development, testing, or debugging. In the case of testing, which is what we will focus on today, it allows for quick and easy tests to be written.
msw的基本思想是创建一个伪造的服务器,该服务器拦截所有请求并像真实服务器一样处理它们。 这意味着您可以将该工具实现为一组“数据库”,从json文件实现“种子”数据,或者实现“构造函数”(如fakerJS),然后创建驱动程序(类似于express API)并与该模拟数据库进行交互。 这使我们可以在非常类似于生产环境的条件下测试应用程序,以进行开发,测试或调试。 在测试中,这是我们今天要关注的重点,它允许编写快速简便的测试。
Once all this is explained, we can move on to writing code.
一旦解释了所有这些,我们就可以继续编写代码。
What we will do this time is a very simple demo of how to work with msw
, we will take as a base a very basic ToDos application made with create-react-app
and exploring the tests with jest
and react-testing-library
.
这次我们将做一个非常简单的演示如何使用msw
,我们将以create-react-app
制作的非常基本的ToDos应用程序为基础,并使用jest
和react-testing-library
探索测试。
Let’s get started.
让我们开始吧。
Installation
安装
msw provides us with an npm package (also available with yarn) to use in our project.
msw为我们提供了一个npm软件包(也可以与yarn一起使用)在我们的项目中使用。
$ npm i msw -D$ yarn add msw — dev
2. Creating our first controller
2. 创建我们的第一个控制器
As we commented previously, msw works with a syntax very similar to what we know from express
making it very fast and easy to build the drivers that will take care of emulating our backend.
如前所述,msw的语法非常类似于express
所知道的语法,从而可以非常快速,轻松地构建将模拟后端的驱动程序。
As we can see in the code, we created a file called server.js
inside a folder called mocks
, in that file we made the import of an object called rest
from msw, since it is the architecture that we will follow, however, it is important to highlight that msw also allows you to emulate the flow if you work with GraphQL.
正如我们在代码中看到的那样,我们在名为mocks
的文件夹中创建了一个名为server.js
的文件,在该文件中,我们从msw导入了一个名为rest
的对象,因为这是我们遵循的体系结构,但是重要的是要强调一点,如果您使用GraphQL ,则msw还可以模拟流。
Besides the import, we created a constant called handlers that will contain all the controllers we want to include in our server. The server object contains methods corresponding to the http verbs like get
and post
, the syntax is very simple, the method only needs to be passed 2 parameters, the url
and a “resolver” which will receive req, res and ctx
which we will explain a little later:
除了导入,我们还创建了一个称为处理程序的常量,该常量将包含我们要包含在服务器中的所有控制器。 服务器对象包含与http动词相对应的方法,例如get
和post
,语法非常简单,该方法只需要传递2个参数,即url
和一个“ resolver”,它将接收req, res and ctx
,我们将对其进行解释一会儿:
req
, contains information about the petition.req
,包含有关请愿的信息。res
, a functional utility that takes care of sending the response.res
,一个功能实用程序,负责发送响应。ctx
, a group of functions that allow us to configure status codes, headers, the body of the response, among other things.ctx
,一组允许我们配置状态码,标头,响应主体等功能的函数。
In order for msw to intercept the request, it is important that we place the url
correctly, there are 3 ways in which msw can evaluate the matches.
为了使msw能够拦截请求,请务必正确放置url
,msw可以通过3种方法评估匹配项,这一点很重要。
Using the exact URL
e.g. http://localhost:4000/todos
使用确切的网址,
eg http://localhost:4000/todos
Using the path
e.g. /todos
使用路径,
eg /todos
- Through regular expressions 通过正则表达式
You can find more information about it here.
您可以在此处找到有关它的更多信息。
3. Jest Configuration
3. 开玩笑的配置
For this step, we are going to take advantage of creating an application with the create-react-app
since it gives us a completely configured environment with the tools we are going to need not only to be able to develop our project but also to be able to test it correctly.
对于这一步,我们将利用通过create-react-app
创建应用程序的优势,因为它为我们提供了一个完全配置的环境,其中包含我们不仅需要能够开发我们的项目的工具,而且还需要能够正确测试。
Inside our project, we’ll find a file called setupTests.js
setupTests.js inside the src
folder, it’s here where we’ll be able to add extra configuration that will be useful in our tests, for example, by default it comes imported the module “@testing-library/jest-dom/extend-expect” that allows us to use affirmations like toBeInTheDocument
or toHaveAttribute
, it’s inside this file where we’ll add the following:
在我们的项目中,我们将在src
文件夹中找到一个名为setupTests.js
的文件setupTests.js
,在这里我们可以添加对测试有用的额外配置,例如,默认情况下它已导入模块“ @testing -library / jest-dom / extend-expect”允许我们使用诸如toBeInTheDocument
或toHaveAttribute
之类的肯定toHaveAttribute
,该模块位于该文件中,在其中添加以下内容:
As we can see, the required configuration is very simple, just import the server we have just configured and added three global conditions for our tests:
如我们所见,所需的配置非常简单,只需导入我们刚刚配置的服务器并为测试添加三个全局条件:
beforeAll
, raise the server so that it is waiting for the requests before my tests start running.beforeAll
,提升服务器,使其在我的测试开始运行之前等待请求。afterEach
, after each test it will reset the drivers to the initial values, and during the tests we can add new drivers that were not defined previously, a topic that we will cover a little later, this to avoid that these new drivers affect other tests.afterEach
,在每次测试之后,它将驱动程序重置为初始值,并且在测试过程中,我们可以添加之前未定义的新驱动程序,稍后将讨论一个主题,以避免这些新驱动程序影响其他测试。afterAll
, after all the tests are finished, we finish the “server”.afterAll
,所有测试完成后,我们完成“服务器”。
By this point we have covered everything we need to configure msw
in our project, but how do we implement it?
至此,我们已经介绍了在项目中配置msw
所需的所有内容,但是如何实现呢?
4. Implementation
4. 实施
Actually the implementation is just as easy as the configuration we have done so far. Let’s consider that we have a simple component that just requests our ToDos from the server and draws them in the browser as follows:
实际上,实现和我们到目前为止所做的配置一样容易。 让我们考虑一下,我们有一个简单的组件,它仅向服务器请求ToDos并将其绘制在浏览器中,如下所示:
Simple, isn’t it? Now let’s create our tests:
很简单,不是吗? 现在让我们创建测试:
We’re already in the home stretch, let’s explain a little what all this code is we have here. First of all, remember that we are going to use testing-library
for our tests, so we import render, screen and waitFor
, the import of react, it’s too much to explain, we import in the same way “server” and “rest”, maybe you wonder why, in a moment we explain it, finally the component that we are going to test in this case App
.
我们已经到家了,让我们来解释一下这里所有这些代码。 首先,请记住,我们将使用testing-library
进行测试,因此我们导入render, screen and waitFor
, render, screen and waitFor
的导入,这解释太多了,我们以“ server”和“ rest”相同的方式导入”,也许您想知道为什么在稍后的说明中,为什么最终要在本例App
测试该组件。
In our first test that we call fetch todos and render
we are testing that the request is being made and our component is handling it correctly, is here where it comes one of the first things that is interesting, remember that the requests are asynchronous processes so these can delay, is for this reason that we need to make use of the waitFor
method, since it will help us to make our test wait for an element with the role of listitem
, once an element of that type is found in the DOM, we can proceed to make our statements, in this case we only made a simple one, the answer of our false “server” returned us only one ToDo (defined in the controller) because the statement consists in that the number of elements that match the role of listitem
is only one.
在我们称为fetch todos and render
的第一个测试中,我们正在测试请求正在执行并且我们的组件正在正确处理它,在这里它是第一个有趣的事情,请记住请求是异步流程,因此这些操作可能会延迟,因此我们需要使用waitFor
方法,因为一旦在DOM中找到该类型的元素,它将有助于我们的测试等待具有listitem
角色的元素,我们可以继续进行声明,在这种情况下,我们只做了一个简单的声明,错误的“服务器”的答案只返回了一个ToDo(在控制器中定义),因为该声明包含与之匹配的元素数量。 listitem
作用只是其中之一。
In this process that we have just explained, we focus on the first test that consists of the successful case, in which everything goes well. Now we’ll look at the other case, when we want to test the failure case.
在我们刚刚解释的这个过程中,我们将重点放在由成功案例组成的第一个测试中,其中一切顺利。 现在,当我们要测试失败案例时,我们将看看另一种情况。
It is very similar to the previous one at the level of statements. However, there is a difference, in our second test we are making use again of the “server” and the rest
object, this with the intention of making that for that specific test, the answer is different, what we are doing is indicating that the answer to the request now has to be a failure and therefore our component has to behave differently and draw the message “http error” that we configured.
在语句级别,它与上一个非常相似。 但是,有一个区别,在第二个测试中,我们再次使用“服务器”和rest
对象,目的是使该特定测试的答案有所不同,我们正在做的事情表明现在,对请求的回答必须是失败的,因此我们的组件必须表现不同并绘制我们配置的消息“ http error”。
Conclusion
结论
This time we reviewed an alternative to emulate our http request process in our applications, we learned how to configure msw.js
a tool that allows us to intercept the requests that are made and respond in the same way that our server would in our testing and development.
这次我们审查了在应用程序中模拟http请求过程的替代方法,我们了解了如何配置msw.js
这个工具,该工具可让我们拦截发出的请求并以与服务器在测试和测试中相同的方式进行响应。发展。
I hope this post will be very useful and help you to make your testing easier, I leave below some references in addition to the full code on Github.
希望这篇文章对您有所帮助,并且可以帮助您简化测试过程 。除了Github上的完整代码外,我还留下了一些参考资料。
Code
码
msb msw