📈 Boost Your Integration Testing for REST APIs with Snapshot Testing in .NET
Tags: testing, dotnet, tutorial, csharp
Published: 2023-04-11 14:28:00

## ⚡ **TD:LR**

- Tests are crucial for software projects, but they should be easy to maintain.
- Classic assertions can become difficult to maintain when contracts change.
- Snapshot testing is an alternative approach to classic assertions.
- In snapshot testing, the first test result is recorded as a snapshot, and subsequent tests are compared against it.
- Snapshot testing makes it easier to maintain tests as the contract changes.
- The article provides a step-by-step guide to implementing snapshot testing for integration tests.
- Snapshot testing has pros and cons, and it’s important to be aware of its limitations.

## Testing is a crucial aspect of any software project 🧪
Tests are necessary to improve and evolve the project. However, with great power comes great responsibility, and tests should be easy to maintain; otherwise, our development process will slow down.

In this article, we will focus on integration testing, particularly for a REST API endpoint that returns a paginated list.

## Classic Assertions Problem 🤯 

There are several ways to assert the results of an API test, such as hard-coding expected items and asserting one item or hard-coding all items and asserting all items. However, when the API is nested and the contract changes, you will need to rewrite your assertions, and you may need to modify several places.

## How to make assertions easier to maintain❓

i would like to highlitht snapshot testing approach (another words approval testing).

![https://ytsp0300.pages.labranet.jamk.fi/images/snapshot-testing.png](https://ytsp0300.pages.labranet.jamk.fi/images/snapshot-testing.png)

Approval testing is a different approach to asserting results. In snapshot testing, we execute the test for the first time and record the output as a snapshot. We then compare subsequent test results against this snapshot to ensure that the API is still behaving as expected. This approach makes it easier to maintain tests as the contract changes since we only need to update the snapshot instead of multiple assertions.

Let’s skip the theory and proceed step by step.

## Step by step Guide 📘
{% embed https://gist.github.com/kamilbaczek/8c7d09a4bf2d18ab88dcb3378204790b.js %}

As you can see, these integration tests are quite ordinary except for one particular feature: the classes have an attribute called **[UseVerify]**. Instead of using traditional assertions, the test results are passed to a function called **Verify()**.

![](https://artofsoftwaredesign.net/wp-content/uploads/2023/04/verify.png)

To work effectively with snapshot testing, I use the Rider Plugin. (Verify Support)

Like you can see on digram we are on the state when we never executed a test a we don’t have snapshot. During Verify function execution git diff window opens.

![](https://artofsoftwaredesign.net/wp-content/uploads/2023/04/verify_snapshot-1024x595.png)

I am reviewing the results of the tests conducted on my function. Based on the test results, I have the option to approve them as expected or reject them and attempt to fix the test. After making any necessary corrections, I can review and approve the results again.

![](https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot2-1024x647.png)

After approval, a text file containing the results is created. This is known as a snapshot.

![](https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot3-1024x110.png)

For example, if we broke something and the method doesn’t return a filled list but instead an empty one, the test will fail.

![](https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot_4-1024x138.png)

![](https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot3-3-1024x110.png)

When adding a property to the contract, a diff will be opened. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76biypsfnssogjgu50ev.png)
After reviewing the changes, you can approve them if they appear correct.

![](https://artofsoftwaredesign.net/wp-content/uploads/2023/04/snapshot_5-1024x110.png)

Although we have made changes to the functionality, the modification of the tests is minimal.

## Use Cases 🤔
It may be worth considering the use of approval testing in cases where writing traditional assertions with loops to cover a large amount of data is time-consuming or difficult. This is particularly true when dealing with complex assertions. For example: 
- testing the output of a report endpoint,
- parsing results from files 
- verifying the results of complex data aggregation endpoints
- apr results that is large or complex data structures, where traditional assertion-based testing may not be practical.
- snapshot testing can be used to verify that database queries it is useful when dealing with complex queries that involve multiple joins and filters.

## Learn by example 📖
- [Product Inventory Example  
](https://github.com/kamilbaczek/Product.Inventory/blob/main/ProductInventory.IntegrationsTests/ProductsControllerTests.cs%0A)

### Trade off analysis 🔖

####👍 Pros:
- Snapshot testing makes it easier to maintain tests as the contract changes.
- It reduces the number of assertions required for testing.
- It reduces the complexity of tests and improves readability.
- It allows developers to see the difference between the current test output and the previous one.
- It is more flexible than traditional assertion testing, allowing developers to test a wide range of scenarios with a single snapshot.

####👎 Cons:
- The test results may be invalid if the developer approves them without reviewing them carefully.
- Snapshot testing may not be suitable for testing scenarios that involve randomness or unpredictable outputs.
- It may not be as precise as traditional assertion testing because it only checks if the output has changed, not how it has changed.
- It may require additional tooling or plugins to work effectively, which may add complexity to the testing process.

As with most things, there are trade-offs. While I like this technique and agree with its consequences, it is important to be aware of its limitations. 

## Follow me
🚀 If you're looking for ways to improve your software development skills and stay up to date with the latest trends and best practices, be sure to follow me on dev.to!📚 I regularly share valuable insights and tips on software development, as well as updates on my latest projects.

Speaking of projects, I'd like to invite you to check out my modular monolith project on GitHub💻, called Estimation Tool. It's a great example of how you can use modularization to build a more scalable and maintainable system. The project is open-source and well-documented, so you can learn by example and see how I applied the concepts of modularization in practice.

https://github.com/kamilbaczek/Estimation-Tool 🔗

So if you're looking to level up your development skills, be sure to follow me on dev.to and check out my modular monolith project on GitHub. Happy coding!🎉