简体   繁体   中英

Best practices for testing a React modal with React Testing Library and Mock Service Worker?

If I were building a simple function that divided one number by another, I would:

  1. In all cases, call the function. The first test would probably be a happy path, like 10 / 2 .
  2. Another test would divide a smaller number by a larger one, resulting in a decimal value.
  3. Some other tests would introduce negative numbers into the mix.
  4. Finally, I would be sure to have one test that divided by zero, to see how that was handled.

I have a series of modals in React that I need to test. They have some commonalities:

  1. They receive a set of props.
  2. They act on those props to display a bunch of elements to the user, pre-populating these elements with some combination of the data in the props.
  3. They use the fireEvent.### functions to simulate what the user would do within the modal.
  4. Near the end of each test that involves a POST or a PATCH, a Submit button is pressed.
  5. After pressing the Submit button, I have two expect functions at the end of each test, like in these examples:
expect(spy).toHaveBeenCalledTimes(1);

expect(spy).toHaveBeenCalledWith({
  type: 'SOME_ACTION',
  payload: {
    property1: 'Some value',
    property2: 'Some other value',
    property3: 53.2
  },
});

This approach entirely makes sense to me because, much like a simple math function, the modal has data coming in and data going out. But some colleagues are insisting that we shouldn't be testing with such expect(spy) functions. Instead they're saying that we should test the end result on the page. But there is no "page" because the modal is being tested in isolation, which I also believe to be a best practice.

Another suggestion was to add a success or failure string to a Mock Service Worker (MSW) response string, like "You've successfully saved the new data". The reason I don't like this approach is because:

  1. Such a string is just an artificial construct in the test, so what does it really prove?
  2. If there are calculations involved with what is sent by the POST or PATCH, don't we want to know whether the correct data is being sent? For example, if the user was prompted to enter the number of hours they worked each day in the past week, wouldn't we want to compare what was entered into the input elements vs. what was sent? And maybe those hours are summed (for some reason) and included in another property that was included - wouldn't we want to confirm that the correct sum was sent?

I do respect the opinions of my colleagues but have yet to hear anything from them that justifies dropping the approach I've employed and adopting one of their alternates. So I'm seeking insight from the community to better understand if this is a practice you would follow ... or not.

This is a case by case scenario with no real answer, as performance and other variables may play a role in making these decisions.

However, based off the information you give both you and your team are right. You would want to validate that the correct data is being sent to the backend yet you would also want to validate that the user is receiving a visual response, such as "Successfully saved data".

Yet if I have to choose one it would be the checking the data as that has the most "code coverage" . Checking for the "success" message simply checks if the submit button was pressed where as the data checking assures that most, if not all, data states were correctly set.

I prefer to do both.

But there is no "page" because the modal is being tested in isolation, which I also believe to be a best practice.

I like doing this because for more complex components, TDD with unit tests keep me sane. Sometimes I build out the unit test just to make sure everything is working, then delete it once the integration tests are up. (Because too much unit tests can be a maintenance burden).

Ultimately I prefer integration tests over unit tests because I've experienced situations wherein my unit tests were passing, but once the component's been nested 3 levels deep, it starts to break. Kent Dodds has an excellent article on it.

My favorite takeaway from the article:

It doesn't matter if your component <A /> renders component <B /> with props c and d if component <B /> actually breaks if prop e is not supplied. So while having some unit tests to verify these pieces work in isolation isn't a bad thing, it doesn't do you any good if you don't also verify that they work together properly. And you'll find that by testing that they work together properly, you often don't need to bother testing them in isolation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM