
Lesson Description
The "Testing Reducers vs Testing Components" Lesson is part of the full, State Management at Scale in React & Next.js course featured in this preview video. Here's what you'd learn in this lesson:
David discusses testing reducers and pure logic separately from components. By focusing on pure functions and immutable updates, tests stay accurate and easier to maintain even as the UI changes.
Transcript from the "Testing Reducers vs Testing Components" Lesson
[00:00:00]
>> David Khourshid: For the last exercise, I want to talk about testing, because testing is very important, of course, as you all know. And when we're testing application logic, this is where all of the principles that we talked about really come into play. Where events are the actual source of truth, state updates are immutable and represented in pure functions, and also doing things like having predictable declarative side effects and normalized data, et cetera.
[00:00:36]
So usually when we're testing react applications, we're really testing the ui. That's the normal de facto way of testing. We're using testing library or vTest, we're rendering our application and, and then we're clicking buttons or filling out fields virtually just to see that everything is working. Now these kinds of tests, which I consider to be a form of end to end tests, are very valuable.
[00:01:05]
So I do recommend, like, don't get rid of them, they're extremely useful. However, they can distract from testing the actual pure business logic. And so this is why when you have a, a pure function that represents your business logic, it is extremely easy to test, because the whole premise of testing is that given an input, we want some sort of expected output when it goes through this function.
[00:01:35]
And that's exactly what a reducer can provide to us. So for instance, if we have a booking reducer and we pass in the initial state and the action that happens, it doesn't matter how that action happens, we just want to know that the actual business logic is correct.
[00:01:53]
So we can assert that different parts of the new state are correct. So that we could say the current step should be hotel after this, and that when we pass in the mock flight, then the selected flight is that mock flight. So just to give you an example, we have a booking reducer here.
[00:02:16]
And again, you can test the UI if you want to, but when the app logic changes, for example, let's say that you add more steps to the booking flow, or you change some sort of internal logic within the booking reducer, then the UI tests actually become pretty difficult to update.
[00:02:34]
And that's because you're not just dealing directly with logic, you, you're dealing with ui, which sort of masks the underlying logic. So if we take a look at the booking reducer, we see a lot of different steps over here. Like we're searching flights, then we're searching the hotels, we're updating the hotels.
[00:02:54]
There's just many different ways that we could go through this flow. And so once we have the initial state, we could actually just test entire flows, especially with the help of AI assisted coding tools and just use that pure function to ensure that we are on the correct state given the events that are passed in.
[00:03:18]
So that's why I actually like doing let state instead of const state, because then I could just reassign it. So we could say state equals booking reducer. Let's make a mock flight. So const model mockFlight. So let's say that we select a flight from a mock airline. We could actually continue through this and just continue to the entire flow.
[00:03:43]
So we can expect that the next step is the hotel search and that the selected flight is the mock flight. Then when we go back to change flight, we could assert that we're actually going this is not the happy path. But we could assert that when the user decides to go back, we're on that previous step and then we could just keep going through there, maybe doing a mock hotel, and we could just basically test entire flows this way.
[00:04:11]
And so this is something where even if your UI completely changes, the testing logic for this application is going to be exactly the same. And so that's why when you're thinking about doing unit tests, really consider putting application logic into that valuable bucket of things that you should unit test.
[00:04:37]
So as you can see, it's very straightforward. We're dealing only with domain specific things and we're not really worried about how do we get to different buttons or inputs in the ui. So I consider testing reducers a very valuable approach because you can test flows like this. Any questions on testing application logic?
[00:05:03]
>> Speaker 2: Have you had experience with Cursor writing unit tests and seeing if it has made some relatively improvements on how it does implementation of your tests?
>> David Khourshid: I think that when you keep things simple, for example, I let cursor generate all of these tests over here and they all look to be correct.
[00:05:28]
Cursor is really good at that, especially because it does have reference to this booking reducer. Everything is in one central place and it understands really well what the flow of this is going to be. However, when it comes to actual UI tests, I've seen that it does get some things wrong a lot.
[00:05:47]
Or really it actually makes the wrong assumptions. So if your UI is in any bit difference than what Cursor would expect from a normal ui, then it might suggest clicking the wrong thing or filling in the wrong field, or just doing whatever it wants with the tests. And the reason for that from an LLM perspective is that when you're dealing with UI, you're dealing with multiple components in multiple different files.
[00:06:17]
And so Cursor has to go through the extra step, if it even does that at all, of piecing together all these files and relating that data together rather than just having it all in one place.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops