To Mock or Not to Mock - That's the Question

Bookmark

To mock or not to mock, that is the question. Whether 'tis nobler for the code of the programmers to engage with spies and stubs in outrageous tests, or to take the real components against a sea of timeouts, and enduring, to validate their code: to commit, to push.

25 min
25 Oct, 2021

AI Generated Video Summary

This Talk discusses the SDC's approach to software development using agile methodologies and extreme programming. It highlights the benefits of pair programming and the use of atomic design in React components. The importance of test-driven development and the React testing library is emphasized, along with the implementation of code, navigation, and form validation using Formik and Yup. The talk also touches on the abstraction layers in software development and the testing of user journeys and accessibility in the BookKeeper app.

1. Introduction to SDC and Agile Development

Short description:

In this talk, we will try to answer the question of whether to mock or not to mock. I am Rita, a geek at heart, living in Lisbon and working at the SDC. The SDC is a software development center established in 2018. We develop products using extreme programming, an agile framework based on communication, simplicity, feedback, courage, and respect. We work in balanced teams, including designers, product managers, and developers. We do test-driven development.

♪ Hi, welcome to this talk. In it, we will try to answer a question, which is, to mock or not to mock? Let's get started.

My name is Rita. I am a geek at heart. I live in Lisbon with my beautiful family. My kid is almost three years old, so he's a bit of a fool plate. But whenever I'm not busying around my family, I'll probably be playing, or I will be at the SDC, the place where I work. I work with these amazing people. And at the moment, I'm part of Team Falcon, and things are slowly starting to get back to normal here at the office.

Where is the office? So, it's a software development center here in Lisbon, and it is right in the middle of the city. It was established in 2018. It was the first software development center that Volkswagen opened outside of Germany. And so far, things have been going very, very smoothly.

What do we do here? So, we develop products using extreme programming. In a nutshell, it is an agile framework that allows us to produce and to deliver high-quality software at a very fast pace with a good quality of life for us, the developers, or for the whole development team. It was created by Kent Beck in 1996. So, it's somewhat old, but the core values that it is based on, they still stand. So, communication, simplicity, feedback, courage, and respect. These five pillars, they are also engraved within the SDC spirit. So, it is a perfect match.

What else can I tell you about the SDC? So, we work in balanced teams, which means that a team is composed of designers, product managers, and us, developers. A team, let me put also some stress in this, a product team, because the team is bigger than just the product teams. The designers, what do they do? So, they keep tabs with the users. They explore, they do the research, they investigate possible avenues to solve the users' problems. The product managers, they will translate these user needs into stories, and they will also keep tabs with the business and see if a product is or isn't viable to be developed by the business point of view. And us, the developers, we will take care of the feasibility in terms of technology. We will be the ones responsible for seeing if something can be integrated with legacy systems, if something can be done using cutting edge technology. If it is technology, that's our realm. In the middle of these three very different roles, that's actually where the magic happens and where good products come to be.

So, what do we do and how do we do it? So, us developers, we do test-driven development.

2. Pair Programming Benefits

Short description:

In pair programming, two developers work together on the same code simultaneously. This practice allows for real-time code review and immediate problem-solving, eliminating roadblocks and fostering efficient collaboration.

Which means first we write some tests, we run the tests, we're expecting to see the tests fail. But the tests pass, the tests pass. No, they shouldn't be passing. Maybe there was a bug in the test, most likely. So, to minimize this type of situations, we also engage in pair programming. Which means that you always get two sets of eyes looking at the same code. We got one computer, two keyboards, two mice, two screens, and that's how we develop. There is no need for code reviews because the code is being reviewed live as you go. You don't get roadblocked because if you do get roadblocked there will be someone there with you. You will be able to express your thoughts, engage in a conversation very quick and efficiently, you'll be able to unblock the train of thought that you have. So it works really well, I have to admit. And I couldn't see myself doing it any other way around.

3. Books and Technological Solutions

Short description:

I'm going to talk to you a bit about books. Books can take you anywhere and tell you stories that you'll never be able to see in real life. We have a library at the SDC, and it's time to bring it to the 21st century. Let's get a technological solution for the bookkeeper and do a couple of sketches to visualize our goals.

So, coming to the core of the presentation. I'm going to talk to you a bit about books. Books, why? Well, books can take you anywhere. They can take you to places and tell you stories that you'll never be able to see in real life. So, we also have a little bit of a library here at the SDC. It is actually two bookshelves with books, but it's a library. So we can get books out of it. Therefore, it has management system. What is it composed of? It's a scratch pad. It's a scratch pad in which we write our name, the book we took, and when we return it, we scratch it back. So, yeah, a little bit. So let's bring this to the 21st century, shall we? What if we dug food on our own methodologies? So instead of having the scratch pad, let's try to get a technological solution for the bookkeeper. So let's talk to the peeps that request and develop the books and deliver back the books to the peeps that have to maintain the library. And let's do a couple of sketches. So this could be what visually we would try to achieve and accomplish. It was a starting point.

4. MVP, Atomic Design, and Coding

Short description:

So let's get an MVP, a proper MVP. We need to add books, borrow books, and return books to the library. We'll use atomic design to organize our React components, starting with atoms, molecules, organisms, and templates. We'll deviate from the original methodology by allowing organisms to have templates. We'll start coding with a blank canvas and aim to achieve test-driven development by developing the page to add a new book and going through the user flow of adding a book to the library.

So let's get an MVP, a proper MVP. And out of the research that we did, the valuable things and the things that posed the most relevant problems to the users were to be able to add books to the library, to be able to borrow books from the library, and to return books naturally. So we can add books. There will be a page for them for such. However, since people tend to be a little bit itchy-trigger on the keyboard, let's also have some validation just to make sure that everything is correct before submitting. Let's have a separate page in which we can see what are the books that are available in the library. Let's have the possibility to actually borrow a book. Um, let's be able to see which books are out there in the world. And let's have the possibility of returning them back to the library.

Okay, these in a very quick overview, these are the sketches that we have. So, now what? How do we go from these sketches to React components that will... Obviously, we will develop this using React. So, how do we go from the sketches to react to our React components? Well, enter atomic design. Atomic design is a way of organizing your components and your visual elements as a design system, most likely. And it is structured in a very straightforward and growing way or increasing in complexity way. You got atoms, you got molecules, when atoms are the simplest ones, molecules are groups of atoms bound together, organisms are groups of molecules and atoms bound together, templates will be canvas where you say, okay, I wanna have this here, this there, this right down here, and then pages when you instantiate the templates. This was how Brad Frost defined the atomic design back in 2013. However, we did some tweaks and some adjustments for our own use. So, we stick to atoms, yes, fine. From our designs, atoms will also be buttons, something very simple. Molecules, a group of atoms bound together or more than just one HTML tag put together. Organisms, such as a book card or a template for the pages for the bookshelves for example. You do get a template and when you instantiate such template, when you do instantiate the template, you will end up with the pages for the bookshelves. However, this is the moment where we broke rank with the original methodology because we said, okay, but organisms can also have templates, which is pretty cool, and as such, we have our deviation.

Okay, so let's get things started and start coding. Where? Okay, you will be able to have the repo that I've used for this presentation available here, and it starts off with something very simple, a blank canvas with a header, a main content, and then the footer. What do we wanna achieve out of this? Okay, we will be doing test-driven development. We will be developing the page to add a new book, and we will be going through the user flow of adding a new book to the library. All good. Let's get started.

5. Test-driven Development and UI Improvement

Short description:

Test-driven development is crucial, and we choose to use the React testing library to write tests that resemble the way our software is used. Starting with the new book page, we render the components and aim to have the form with all the elements, including a disabled save button. Initially, the tests fail due to missing production code. By correcting spelling errors and using regex, we ensure the tests pass. However, the UI still needs improvement. To address this, we write additional tests and tweak the React testing library to mock and call the necessary components.

Test-driven development, which means we'll have to write tests. To write tests and having the user at the center of it all, we have been choosing to use the React testing library because, as Kenti Dodds said in a very elegant way, the more your tests resemble the way your software is used, the more confidence they give you. And this is in fact something that we resonate with and that we think is a good way of going through the test-driven development.

So we'll be using the React testing library for this. Let's get started with the new book page. What do we have here? Okay, we have the form that will contain the save button disabled. We will render just the components, or in this case, the page, to have the better off. It will be the component. The component to have the form for writing a new book with all of the elements, the header, the different input sections, the buttons, and ideally, to have the button disabled. Simple test.

Of course, it fails because there is nothing to be, there is nothing. The component is clean. We haven't done any of the production code. So let's get to it. When you add some of the production code, you rerun the tests and your tests are still failing. Why are they failing? Because we were a little bit permissive of the test and then the person who implemented the code was a little bit late with the typing. So instead of having author properly spelled, we were somewhat creative. Why? Because the test was using regex, so it allowed us to be a little loose with the definition of the string. If you fix it for the correct spelling, your test gets to pass. Okay, cool. But we're front-end developers, so we always like to see how things are.

And this is how things look, which isn't brilliant, is it? So let's try and fix it. How can we fix it? We can write another test. And instead of using the React testing library as it is meant to be used, let's tweak it a little bit. You remember the input molecule? Let's say that we wanna call it. Let's mock it and let's say that we wanna call it with the parameters that we're expecting to see. Let's do the same for the OK and Cancel buttons as a molecule and let's go for it. Yeah, we know. Yeah, obviously it's not called. So let's call it.

6. Implementing Code, Navigation, and Formic with YUP

Short description:

When you do implement the code, your test gets to pass. Easy. It's mission accomplished. And as a bonus, when you get to see how it looks, ta-da. Yes, this is what we want. We're getting somewhere. Furthermore, when we click on the Cancel button, research showed we would like to be taken back to the homepage. So for that, let's use the React Router DOM so that we can do navigation between our pages. I've showed you two different ways of going on and about for this simple component, this simple form. Pros and cons. When you have Forms, my strong advice is for you to go with Formic with the combination of Formic and YUP for its validation. It is better tested, it is amazing, I have to say, and it is somewhat easy to get acquaintance with. So let's get down to business with Formic and YUP.

When you do implement the code, your test gets to pass. Easy. It's mission accomplished. And as a bonus, when you get to see how it looks, ta-da. Yes, this is what we want. We're getting somewhere.

Furthermore, when we click on the Cancel button, research showed we would like to be taken back to the homepage. So for that, let's use the React Router DOM so that we can do navigation between our pages. So let's expect the history push to have been called. It really hasn't has it, so, yeah, we know it hasn't been called, so let's call it. When we do call it, both know when we call it on the callback for the Uncancel, our test gets green, and all good. Super, easy. Very easy.

I've showed you two different ways of going on and about for this simple component, this simple form. Pros and cons. When you do mock the components, you get an easy going from the designs to the components that you're using, which is cool. You don't get to cheat on the components that you use, because if you wanna use our button, you're gonna use our button, you're not gonna use the HTML Tag for Button. When you render your component, you get to do so in a controlled environment, so you get to mimic the navigation back and forward or wherever you wanna go with a lot of... Or the other way around, with not that much trouble. However, the downside of it is that you do have some shallow rendering going on, which I know, it's totally against what the React Testing Library stands for, but then again, pros and cons. Eventually, you might end up with some duplicate tests here and there. Which is okay, and you have a tight coupling with the implementation details. We said we wanna use the React Router DOM. That's what we're gonna use to do navigation. Pros and cons. There's no right or wrong here.

Moving on. When you have Forms, if this is new to you, when you have Forms, my strong advice is for you to go with Formic with the combination of Formic and YUP for its validation. It is better tested, it is amazing, I have to say, and it is somewhat easy to get acquaintance with. So let's get down to business with Formic and YUP.

7. Formic Testing and Service Documentation

Short description:

On the tests, we mock Formic and expect it to be called. However, we decide to use Formic as it is, without mocking. We focus on the part when we're going to submit and test the service to add a book, which calls the slash-API slash books endpoint with the given payload.

On the tests, how do you make sure that you're using Formic? So you mock it, and you expect it to have been called. Easy. It's not called, yeah, obviously it's not. Of course it's not because we just introduced it. We do call it like this, and the test passes. But if only it was this simple. So maybe we should go and read a little bit more about Formic. So, on Formic you get the basic example, and out of it you can pretty much spot that we need to give more information to Formic, so the initial values and what we wanna do when we submit, and speaking of submit, we will want to do so. But the button is disabled. We wanna click it. How do we click it, how do we enable the buttons? Okay, furthermore digging, and we discovered that there is this valid property that goes along with the dirty, and then we'll have to see how we can use it in the forms, but pause. What do we wanna do? Do we wanna spend time learning how to mock this third party library? Or do you wanna spend time using it? The answer is fairly simple, which means let's talk about it. We need to decide what we wanna do. And as a team, we have decided that we wanna use Formic as it is, so no mocking. We go for it fair and square, and we do so. So, instead of having all of the forms, we just focus on the part when we're going to submit. So, when we're going to submit, we are going to have a service to add the book, and we will be expecting it to be called, but it's not, obviously. So, if we go to the form that we have, and that is already populated with more of the Formic stuff, we get to call the add book. And we've got a green test passing. So, easy peasy. No biggie. But what is this? What is this service? This service is documented through the tests. So, it's another advantage of test-driven development. The tests are your documentation. They will be your reference for the things and for the information that you need to extract. So, the service to add book is merely a service that calls the slash-API slash books endpoint with the given payload. Just that, not much. So, there you go. It calls the fetch that is from a fetch service that in turn is something that we have in the bookkeeper that is encapsulating the fetch API. So, it's a couple of layers going on here.

8. Layers and Abstraction in Software Development

Short description:

But Trek told us that layers are good. Layers are cool. Why do we have layers? When you have layers in this case, you get a lot of abstraction. You're able to ignore the specific libraries or APIs you're using and focus on the fetch service. Mocking the service makes testing easier, but you may need to dig to understand the services and their locations.

But Trek told us that layers are good. Layers are cool. Why do we have layers? Procon. When you do have layers in this case, you get a lot of abstraction here. So, you're able to ignore if you're using the fetch API, axios, node fetch, a library that you've built on your own. We don't really care. It's hidden away, tucked under the fetch service that is used throughout the entire application. And you're good for it. And you're also good for mocking it. So instead of trying to mock all of the places where you use the library, you can just mock the call to the service. It makes it a lot easier to test. However, you will end up with some digging that you'll need to do if you wanna understand what are the services and where they are.

9. Testing User Journey and Accessibility

Short description:

Now we can focus on an entire journey for Bob using the BookKeeper app. Render the entire app without mocking, except for Global Fetch. By focusing on the user journey, you can test the React components and navigation. This approach allows you to simulate an end-to-end test without the need for a running backend. You can also prioritize accessibility and test the application from the user's perspective.

So to wrap up, now we can focus on an entire journey for Bob. So Bob wants to use the BookKeeper. So he wants to use the BookKeeper, which is the name of our app, if you haven't noticed. So you render the entire app, all of it. No mocking whatsoever, except Global Fetch, which is the uttermost part of your app, when you do mock this uttermost part. You get to be very, very focused on the user journey. Take it with far and square through the React testing library flows, and of course, the test will fail because test-driven development. Remember, we started with a blank canvas on the BookKeeper. So, let's add stuff. Let's add the navigation with the React RouterDOM, switching between the homepage, the page to add new books, and eventually the page to borrow books. Things would pass. Pros and cons in this approach. You can probably say that, yeah, that looks a lot like an end-to-end test, and we could be doing this using Cypress instead of the React testing library within the front-end development. Yeah, you could. But if you do it like this, you actually get to focus on the user journey, which is something that you could also do in the end-to-end. Fair. But in this case, you don't have to worry about having a backend up and running. You just need to be mindful of what are the endpoints, and what is the interface that your backend is providing you. Then you can simply go ahead and mock the responses that you want to have. You can also focus on accessibility. You can test your whole application through the eyes of the user, how he perceives your application, and that is something that is really valuable. The cons of this part... I really didn't find any, so kind of, sorry.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.


React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Advanced Conference 2021React Advanced Conference 2021
47 min
Design Systems: Walking the Line Between Flexibility and Consistency
Design systems aim to bring consistency to a brand's design and make the UI development productive. Component libraries with well-thought API can make this a breeze. But, sometimes an API choice can accidentally overstep and slow the team down! There's a balance there... somewhere. Let's explore some of the problems and possible creative solutions.


TestJS Summit 2021TestJS Summit 2021
34 min
Network Requests with Cypress
Whether you're testing your UI or API, Cypress gives you all the tools needed to work with and manage network requests. This intermediate-level task demonstrates how to use the cy.request and cy.intercept commands to execute, spy on, and stub network requests while testing your application in the browser. Learn how the commands work as well as use cases for each, including best practices for testing and mocking your network requests.
TestJS Summit 2021TestJS Summit 2021
38 min
Testing Pyramid Makes Little Sense, What We Can Use Instead
Video
The testing pyramid - the canonical shape of tests that defined what types of tests we need to write to make sure the app works - is ... obsolete. In this presentation, Roman Sandler and Gleb Bahmutov argue what the testing shape works better for today's web applications.


React Summit 2023React Summit 2023
24 min
React Concurrency, Explained
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar

Workshops on related topic

React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Workshop
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.
You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.


React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Workshop Free
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.
The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.
React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.


React Summit 2023React Summit 2023
171 min
React Performance Debugging Masterclass
Workshop Free
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Summit 2023React Summit 2023
152 min
Designing Effective Tests With React Testing Library
Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents
- The different kinds of React application tests, and where component tests fit in
- A mental model for thinking about the inputs and outputs of the components you test
- Options for selecting DOM elements to verify and interact with them
- The value of mocks and why they shouldn’t be avoided
- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites
- Familiarity with building applications with React
- Basic experience writing automated tests with Jest or another unit testing framework
- You do not need any experience with React Testing Library
- Machine setup: Node LTS, Yarn
TestJS Summit 2022TestJS Summit 2022
147 min
How to Start With Cypress
Workshop Free
The web has evolved. Finally, testing has also. Cypress is a modern testing tool that answers the testing needs of modern web applications. It has been gaining a lot of traction in the last couple of years, gaining worldwide popularity. If you have been waiting to learn Cypress, wait no more! Filip Hric will guide you through the first steps on how to start using Cypress and set up a project on your own. The good news is, learning Cypress is incredibly easy. You'll write your first test in no time, and then you'll discover how to write a full end-to-end test for a modern web application. You'll learn the core concepts like retry-ability. Discover how to work and interact with your application and learn how to combine API and UI tests. Throughout this whole workshop, we will write code and do practical exercises. You will leave with a hands-on experience that you can translate to your own project.
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Workshop Free
- Introduction
- Prerequisites for the workshop
- Fetching strategies: fundamentals
- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)
- Test your build and serve it on Vercel
- Future: Server components VS Client components
- Workshop easter egg (unrelated to the topic, calling out accessibility)
- Wrapping up