当前位置: 首页 > 工具软件 > Behave.js > 使用案例 >

jest.conf.js_如何在Jest中正确模拟Moment.js / dates

上官和惬
2023-12-01

jest.conf.js

by Iain Nash

由伊恩·纳什(Iain Nash)

如何在Jest中正确模拟Moment.js / dates (How to correctly mock Moment.js/dates in Jest)

Times and dates are infamously hard to correctly implement in code. This makes testing date and time code correctly important. Testing allows for reasoning around logic in code and also to allow catching edge cases or errors before they impact users.

众所周知,时间和日期很难在代码中正确实现。 这使得测试日期和时间代码正确重要。 测试可以围绕代码中的逻辑进行推理,还可以在影响用户之前捕获边缘情况或错误。

A common mistake when testing date and time code is to not set the current time to a static time. If code in the UI renders today’s date and is tested properly, that test that only works until the current time changes too much. Javascript exposes the built-in Date object which allows for retrieving the current time through construction with no arguments or a call to the now() property.

测试日期和时间代码时的一个常见错误是不将当前时间设置为静态时间。 如果用户界面中的代码呈现了今天的日期并经过了适当的测试,则该测试仅在当前时间变化太大之前才起作用。 Javascript公开了内置的Date对象,该对象允许通过构造检索当前时间,而无需传递参数或调用now()属性。

Moment.js is a popular front-end date manipulation library that is commonly used to manipulate, load, format, and shift time. It uses an empty constructor to get the current time. Jest is often used in conjunction with Moment and React applications. Additionally, Jest snapshot testing introduces new dependencies on date and time that are important to consider. Below is an example problematic component that renders the current day:

Moment.js是一个流行的前端日期处理库,通常用于处理,加载,格式化和转换时间。 它使用一个空的构造函数来获取当前时间。 Jest通常与Moment和React应用程序结合使用。 此外,Jest快照测试引入了对日期和时间的新依赖关系,需要加以考虑。 以下是呈现当前日期的示例问题组件:

An initial test for the TodayIntro component could look like:

TodayIntro组件的初始测试可能类似于:

However, this test will fail on any day that is not Jan 23rd. A solution to this is to override Javascript’s date function to return a known date to work against when writing tests.

但是,该测试将在1月23日之前的任何一天失败。 一种解决方案是重写Javascript的date函数,以在编写测试时返回一个已知的日期作为工作基准。

This code overrides the Date constructor to set a static “current” date:

此代码覆盖Date构造函数以设置静态的“当前”日期:

An ineffective solution is to do the date math yourself against the current time the test is run. This is an ineffective test because you’re running the same code you’re testing to test the return value. For instance, if testing by comparing formatted dates through moment, one would not catch if the moment formatting code changes MMM to JAN instead of Jan .

一种无效的解决方案是根据测试的当前时间自己进行日期数学计算。 这是无效的测试,因为您正在运行与测试返回值相同的代码。 例如,如果通过比较时刻中的格式化日期进行测试,则当时刻格式化代码将MMM更改为JAN而不是Jan ,将无法捕获。

为Jest / JS设置静态时间和时区的方法 (Ways to set a static time and timezone for Jest/JS)

  1. Use a library to mock out Date object to return a static date and timezone (we’d recommend MockDate for simple cases, but read on for a breakdown of the alternatives)

    使用库模拟出Date对象以返回静态日期和时区(对于简单的情况,我们建议使用MockDate ,但请继续阅读以了解替代方法的细目分类)

  2. Mock moment().format() to return a static string

    模拟moment().format()返回一个静态字符串

  3. Mock the Date constructor and now() function to return a static time

    模拟Date构造函数和now()函数以返回静态时间

Using a library in this case is preferable because these libraries are well tested, do not introduce boilerplate code and handle transparently both cases dates can be created (Date.now() vs new Date() etc.). Additionally, using a library allows for easily following test code and setting a specific time per test which allows for better testing practices.

在这种情况下,最好使用一个库,因为这些库已经过良好的测试,不会引入样板代码,并且透明地处理两种情况下都可以创建日期( Date.now()new Date()等)。 此外,使用库可以轻松遵循测试代码并为每个测试设置特定的时间,从而可以实现更好的测试实践。

  • MockDate provides further functionality for time zones and is easy to use

    MockDate提供更多功能,并且易于使用

  • sinon provides Date and timer (setTimeout etc.) mocks

    sinon提供了Date和timer( setTimeout等) sinon

  • Manually setting the mock can be useful in limited environments, however, can become rather complicated

    手动设置模拟在有限的环境中可能很有用,但是会变得相当复杂
  • jasmine (not included in jest), comes with a jasmine.clock()

    jasmine (不包含在笑话中),带有一个jasmine.clock()

The examples below use MockDate, which only focuses on mocking the Date object simply and handles testing time zone offsets as well for testing local time zone conversion.

下面的示例使用MockDate ,它仅专注于简单地模拟 Date对象,并处理测试时区偏移以及测试本地时区转换。

A snapshot test, as well, is simple to test with mocked dates:

快照测试也很容易使用模拟日期进行测试:

Since enzyme is an awesome library, an enzyme shallow example:

由于是一个很棒的库,因此酶浅的例子:

如何(更好)测试日期逻辑 (How to (better) test date logic)

Dates have a lot of edge cases and logic behind them. When testing dates, make sure to cover edge cases and not just set one specific date to test and move on. Dates can also vary according to locale and time zone.

日期背后有很多极端情况和逻辑。 测试日期时,请确保覆盖一些极端情况,而不仅仅是设置一个特定的日期进行测试并继续进行。 日期还可以根据地区和时区而变化。

Properly testing dates require reasoning around edge cases that could occur and writing tests to ensure those edge cases behave as expected and that future changes to code or libraries used in your application don’t break those assumptions. Additionally, adding code to set the current date and time to a static date and time across all test code may be easier, but prevents good reasoning around testing Dates and hides test assumptions in library code.

正确的测试日期需要围绕可能发生的边缘案例进行推理,并编写测试以确保这些边缘案例的行为符合预期,并且将来对应用程序中使用的代码或库的更改不会破坏这些假设。 此外,添加代码以将所有测试代码中的当前日期和时间设置为静态日期和时间可能更容易,但是会阻止围绕测试日期进行充分的推理,并在库代码中隐藏测试假设。

Here are a few incorrect and often implicit assumptions about dates:

以下是一些关于日期的不正确且通常是隐含的假设:

  1. Clients all exist within one time zone and daylight saving time

    客户全部存在于一个时区和夏令时
  2. All clients exist within the developer’s time zone

    所有客户都存在于开发人员所在的时区
  3. The length of a Month name is relatively similar

    一个月名称的长度相对相似
  4. Server clocks are always correct

    服务器时钟始终正确
  5. The server knows the client’s timezone/time settings

    服务器知道客户端的时区/时间设置

This test assumes the server is always in the correct timezone and that timezone is set correctly. Instead, set the timezone and make sure the date matches the local timezone correctly.

此测试假定服务器始终处于正确的时区,并且该时区已正确设置。 而是设置时区并确保日期正确匹配本地时区。

It is important to ensure that when tests access the current time the “current time” is set to a static value. If the value is dynamic, either tests eventually break or a test is testing against dynamic values. Dynamic values are not effective at testing behavior since a bug will not be exposed by comparing the return value of two functions that are the same as compared to comparing to a static value that doesn’t change as the code is modified.

确保测试访问当前时间时,“当前时间”设置为静态值非常重要。 如果值是动态的,则测试最终会中断,或者测试正在针对动态值进行测试。 动态值对测试行为无效,因为通过比较两个函数的返回值(与将其修改后不会改变的静态值进行比较)相比,不会发现错误,因此不会暴露出错误。

展望未来:日期时间存储和设计 (Looking ahead: Date time storage and design)

Having a requirement to add tests to a code base doesn’t necessarily provide any value unless those tests are reviewed, run, and reasoned about just as strictly as running code.

要求将测试添加到代码库中并不一定能提供任何价值,除非对这些测试的审查,运行和推理与运行的代码一样严格。

Date and time logic introduces a large set of possibilities in terms of behavior and output, making a strong incentive to test effectively for date and time. Beyond testing, acknowledging and keeping relevant data along with a strategy to synchronize and store date times consistently across systems early on both helps testing and makes for a better user experience.

日期和时间逻辑从行为和输出方面引入了大量可能性,这强烈激励了人们对日期和时间进行有效测试。 除了测试之外,确认和保留相关数据以及在整个系统上尽早同步和存储日期时间的策略,不仅有助于测试,而且可以带来更好的用户体验。

These tips and approaches apply to more than just Javascript & Jest testing for dates and times. They also work in a NodeJS context and in a general sense around key things to test for in systems that handle date and time in general. In many cases, storing time on the server in UTC (Universal coordinated time) then converting to the local time zone based on client / browser settings is ideal. If the client is inaccessible, storing both the UTC time and user’s actual timezone is an effective way to consistently treat dates and times.

这些技巧和方法不仅适用于Javascript&Jest测试日期和时间。 它们还可以在NodeJS上下文中以及通常意义上围绕关键事物工作,以在通常处理日期和时间的系统中进行测试。 在许多情况下,理想的情况是将时间存储在服务器上的UTC时间(通用协调时间),然后根据客户端/浏览器设置转换为本地时区。 如果无法访问客户端,则同时存储UTC时间和用户的实际时区是一种有效地处理日期和时间的有效方法。

翻译自: https://www.freecodecamp.org/news/how-to-correctly-mock-moment-js-dates-in-jest-25fa2528ca11/

jest.conf.js

 类似资料: