E2E Tests for API – Saving Nerves and Hours

Rate this content
Bookmark

Having adequate test coverage means a lot for the good API. But what can make the whole life pathetic is endless mocking of data and functions for integration tests. Every time you've changed the code you need to fix the mock. After several iterations the correct thought is - what's went wrong?


Alternative approach is e2e tests for the API. Which require only minimal mocks and data preparation. The rest - pure code of your API. Change the code - e2e test remains the same.

This talk is about my experience of switching from integration tests to e2e tests for the API, proc and cons and how I started to feel happy about tests.

This talk has been presented at TestJS Summit 2021, check out the latest edition of this JavaScript Conference.

FAQ

Valentin Kononov's talk focuses on the implementation and benefits of end-to-end tests for APIs, sharing his experiences and methods to improve testing efficiency and reduce the need for constant updates in test mocks.

Kononov faced challenges with integration tests due to the need for frequent updates of mock dependencies whenever minor changes were made to the code, leading to a significant increase in maintenance time and effort.

According to Valentin Kononov, end-to-end tests differ from integration tests as they involve testing the complete workflow of an API in a real-world scenario without relying heavily on mocks, thus testing the system more comprehensively.

End-to-end tests offer several advantages including a more thorough validation of the whole system, reduced reliance on mocks, easier modifications, and they serve as additional documentation, enhancing the overall development and maintenance process.

Valentin recommends using simple, reusable mocks for authentication guards in end-to-end tests, which are easy to write and can be used consistently across different tests, simplifying the testing process.

In his talk, Valentin describes an API test where a POST request is sent to an endpoint with project data, expecting a 201 response code for successful creation, followed by a GET request to verify the correct properties of the response.

A common pitfall in API testing is the time-consuming process of updating mock dependencies with code changes. Valentin addresses this by advocating for end-to-end tests, which reduce the dependency on mocks and streamline the testing process.

Valentin shares a trick for mocking dates in tests, where not only the 'now' function is mocked, but also the constructor, providing a more comprehensive solution for manipulating date values in test environments.

Valentin Kononov
Valentin Kononov
8 min
19 Nov, 2021

Comments

Sign in or register to post your comment.
Video Summary and Transcription
This Talk discusses the use of end-to-end tests for API development, specifically using the Nest.js framework. The process of initializing the Nest API for testing is explained, along with customization options such as overriding authentication guards. The benefits of end-to-end tests are highlighted, including ease of modification and serving as additional documentation for the API. The challenges of writing the initial version of the test and a trick for mocking the date in tests are also mentioned.

1. Introduction to End-to-End Tests for API

Short description:

Hello, everyone. My name is Valentin Kononov, and today my lightning talk is about end-to-end tests for API. How I did it. How it saved my nerves and hours and so on so forth. But still just a little bit about myself. So, I am a developer, mostly working with TypeScript and JavaScript these days, so with Node.js, and especially with the backend. And on one of my last projects, we had a backend written in NestJS, and we struggled a lot with testing it, especially when we need to change some functionality. That's how we tried to eventually move to end-to-end test, and here is what my talk about.

Hello, everyone. My name is Valentin Kononov, and today my lightning talk is about end-to-end tests for API. How I did it. How it saved my nerves and hours and so on so forth.

But still just a little bit about myself. So, I am a developer, mostly working with TypeScript and JavaScript these days, so with Node.js, and especially with the backend. And on one of my last projects, we had a backend written in NestJS, and we struggled a lot with testing it, especially when we need to change some functionality. That's how we tried to eventually move to end-to-end test, and here is what my talk about.

At the moment, I'm working at a Unity company, and it's all about fun and games and stuff, but I am working in the advertisement department, so we have a lot of services and both frontend and backends, and of course, we need to test them carefully.

Straight to the point, we don't have too much time. When we talk about API testing, what do we usually mean? First of all, we need to test the data flow, so how the data flows through our services, what are DB queries, so what input, output and data transformers. And in most cases, we just need to test if crude operations work fine and the syndication work fine and all the endpoints are correct, and what we usually do to achieve that. Of course, in most cases, we have integration tests.

And how does it work? Integration tests usually test the whole module, like the whole service, but the service is not something which is present by itself, it's something which communicates with other modules like a database or data repository or some syndication model, something else. So that's why to test it, we need to mock some dependencies. And when we did that and the test is working fine, what do we do next? We update the code, we make some new features. And what do we need to do next? We need to update the mock dependencies, so that the test keeps working. And what else? Yes, we need to update mock dependencies once again, and again, and again, and again.

So I really faced it. We had a really big, important, super mega-critical test about some export process. And every time we changed a minor thing in the export code, we needed to completely rewrite the whole test. That was bad. So, how usually the integration test could look like with all the mocks? So it's actually a huge pile of different kinds of mocking functions, like you see in the slides. Sometimes we mock the whole module, sometimes we mock just one function. And of course, when something is changed in the function, especially in the last example here, the update function was changed, and its output was changed. Even the format of output, like it was an object, became just one simple number. So, we needed to update the mock. And that actually sucked because we spent a lot of time just for supporting the tests. But it should be vice versa, so tests should save all the time for the development. So is there any alternatives of how we can proceed so that the whole process would be easier for us as developers? Basically, my recipe for that was end-to-end tests.

2. End-to-End Tests for API

Short description:

We discussed using the Nest.js framework for end-to-end tests in API development. End-to-end tests involve starting up the entire API in a testing environment and testing it point by point. The initialization of the Nest API involves creating a testing module, initializing it, and creating a Nest application. Tests can be customized by overriding authentication guards. The tests themselves involve making POST or GET requests to specific endpoints, sending request data, and expecting specific response codes and properties. End-to-end tests have pros such as being easy to fix, modify, and serving as additional documentation for the API. However, writing the initial version of the test can take time, especially when data preparation is required. A trick for mocking the date in tests is also shared.

We discussed with the team, okay, we have Nest.js framework. It has a lot of testing capabilities. So why don't we use it for end-to-end tests? And what is the end-to-end test for when we're talking about the API? It's when you start up the whole API, like the whole node service in your testing environment, and you test it at point by point.

So in this slide, you can see how initialization of the Nest API could look like. So you see, create testing module, you initialize it, you're like, create Nest application. In the end, you should close it and of course you can overwrite anything you want. For example, Nest, we use so-called guards for authentication. Here, we can override it, initialize and close in the very end when all the tests passed. And authentication guard mock is a pretty simple thing, which you just write once and use everywhere. It's really such simple stuff.

And here is how the whole test would look like. So you literally request, you do a POST or GET request to some certain endpoint, for some certain URL. And in this sample, because it's POST, you can send somebody details, like what kind of project data we should add. And you can expect, like here in the last line, you can expect some kind of code, like it should return 201. Which means successfully created. And you can also do a GET request and also form some URL, send requests, expect some code. And also expect some response. And check that the response properties are correct.

What do you mean? So the pros and cons. The pros, easy to fix, easy to modify and you test the whole workflow. And as you see right here the whole test is very readable and it's also an additional source of documentation for your API. But of course there are some cons and bad sides. So it can take time to write the initial version of this test because in some cases you need to prepare the data. Of course when you have just a crude API you can use just only get or post requests to create data and to make sure it's created. But in some cases you need to prepare the data in a database and this minimal database should be run somewhere in a continuous integration service. And just for you we have a really special trick, really small. Sometimes, in my experience, only once. But we needed to fake the date. I prepared some data and I should make sure that this data is created with this date now. And usually we did it like that. But in some code we actually use not just the now function, but also construct. And there is a little bit more comprehensive solution of how to mock the date for both places for now and for the constructor. So just make a screenshot, it's a very useful trick, see you later.

And here's the link for my slides, my website and my doc, which inspired me for all of that stuff. So, as a summary, make tests. It's really a great thing when you do tests. And entering tests makes the changes faster and you can cover the whole workflow with the last mocks and be much more happy.

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

Routing in React 18 and Beyond
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Routing in React 18 brings a native app-like user experience and allows applications to transition between different environments. React Router and Next.js have different approaches to routing, with React Router using component-based routing and Next.js using file system-based routing. React server components provide the primitives to address the disadvantages of multipage applications while maintaining the same user experience. Improving navigation and routing in React involves including loading UI, pre-rendering parts of the screen, and using server components for more performant experiences. Next.js and Remix are moving towards a converging solution by combining component-based routing with file system routing.
Network Requests with Cypress
TestJS Summit 2021TestJS Summit 2021
33 min
Network Requests with Cypress
Top Content
Cecilia Martinez, a technical account manager at Cypress, discusses network requests in Cypress and demonstrates commands like cydot request and SCI.INTERCEPT. She also explains dynamic matching and aliasing, network stubbing, and the pros and cons of using real server responses versus stubbing. The talk covers logging request responses, testing front-end and backend API, handling list length and DOM traversal, lazy loading, and provides resources for beginners to learn Cypress.
Testing Pyramid Makes Little Sense, What We Can Use Instead
TestJS Summit 2021TestJS Summit 2021
38 min
Testing Pyramid Makes Little Sense, What We Can Use Instead
Top Content
Featured Video
Gleb Bahmutov
Roman Sandler
2 authors
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.
Testing Web Applications with Playwright
TestJS Summit 2022TestJS Summit 2022
20 min
Testing Web Applications with Playwright
Top Content
Watch video: Testing Web Applications with Playwright
Testing web applications with Playwright, a reliable end-to-end testing tool. Playwright offers fast execution, powerful tooling, and support for multiple languages. It provides precise selectors, web-first assertions, and code generation for easy testing. Playwright also offers features like live debugging, tracing, and running tests on CI. The future of Playwright aims to make testing easy and fun, with a focus on creating frustration-free web experiences.
A Practical Guide for Migrating to Server Components
React Advanced 2023React Advanced 2023
28 min
A Practical Guide for Migrating to Server Components
Top Content
Watch video: A Practical Guide for Migrating to Server Components
React query version five is live and we'll be discussing the migration process to server components using Next.js and React Query. The process involves planning, preparing, and setting up server components, migrating pages, adding layouts, and moving components to the server. We'll also explore the benefits of server components such as reducing JavaScript shipping, enabling powerful caching, and leveraging the features of the app router. Additionally, we'll cover topics like handling authentication, rendering in server components, and the impact on server load and costs.
Full-Circle Testing With Cypress
TestJS Summit 2022TestJS Summit 2022
27 min
Full-Circle Testing With Cypress
Top Content
Cypress is a powerful tool for end-to-end testing and API testing. It provides instant feedback on test errors and allows tests to be run inside the browser. Cypress enables testing at both the application and network layers, making it easier to reach different edge cases. With features like AppActions and component testing, Cypress allows for comprehensive testing of individual components and the entire application. Join the workshops to learn more about full circle testing with Cypress.

Workshops on related topic

Designing Effective Tests With React Testing Library
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
Josh Justice
Josh Justice
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
AI for React Developers
React Advanced 2024React Advanced 2024
142 min
AI for React Developers
Featured Workshop
Eve Porcello
Eve Porcello
Knowledge of AI tooling is critical for future-proofing the careers of React developers, and the Vercel suite of AI tools is an approachable on-ramp. In this course, we’ll take a closer look at the Vercel AI SDK and how this can help React developers build streaming interfaces with JavaScript and Next.js. We’ll also incorporate additional 3rd party APIs to build and deploy a music visualization app.
Topics:- Creating a React Project with Next.js- Choosing a LLM- Customizing Streaming Interfaces- Building Routes- Creating and Generating Components - Using Hooks (useChat, useCompletion, useActions, etc)
How to Start With Cypress
TestJS Summit 2022TestJS Summit 2022
146 min
How to Start With Cypress
Featured WorkshopFree
Filip Hric
Filip Hric
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.
Build a Headless WordPress App with Next.js and WPGraphQL
React Summit 2022React Summit 2022
173 min
Build a Headless WordPress App with Next.js and WPGraphQL
Top Content
WorkshopFree
Kellen Mace
Kellen Mace
In this workshop, you’ll learn how to build a Next.js app that uses Apollo Client to fetch data from a headless WordPress backend and use it to render the pages of your app. You’ll learn when you should consider a headless WordPress architecture, how to turn a WordPress backend into a GraphQL server, how to compose queries using the GraphiQL IDE, how to colocate GraphQL fragments with your components, and more.
Detox 101: How to write stable end-to-end tests for your React Native application
React Summit 2022React Summit 2022
117 min
Detox 101: How to write stable end-to-end tests for your React Native application
Top Content
WorkshopFree
Yevheniia Hlovatska
Yevheniia Hlovatska
Compared to unit testing, end-to-end testing aims to interact with your application just like a real user. And as we all know it can be pretty challenging. Especially when we talk about Mobile applications.
Tests rely on many conditions and are considered to be slow and flaky. On the other hand - end-to-end tests can give the greatest confidence that your app is working. And if done right - can become an amazing tool for boosting developer velocity.
Detox is a gray-box end-to-end testing framework for mobile apps. Developed by Wix to solve the problem of slowness and flakiness and used by React Native itself as its E2E testing tool.
Join me on this workshop to learn how to make your mobile end-to-end tests with Detox rock.
Prerequisites- iOS/Android: MacOS Catalina or newer- Android only: Linux- Install before the workshop
Next.js 13: Data Fetching Strategies
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
Alice De Mauro
Alice De Mauro
- 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