Write an Integration test, not a Unit test
Alex Kondrashov
Posted on May 4, 2022
As a lazy software engineer I want to write code only when necessary. If I happen to write code I want to utilise it as much as possible. If this sounds like you, then let’s look at how Integration tests can allow your code to be more efficient.
Too Long To Read
Write both, Integration and Unit tests, when you have enough time or it’s a critical piece of your system. Write Integration tests first when time is off the essence.
More…
Integration test — is a type of software testing in which the different units, modules or components of a software application are tested as a combined entity.
Unit test proves correct work of one unit only. Whereas an Integration test proves work of more than one unit.
System Under Test
Why is it important to understand what is System Under Test? It will help us define the efficient test.
System under test (SUT) — system that is being tested for correct operation.
It’s normal that Integration test covers wider SUT than a Unit test. Let’s consider the following test:
[Fact]
public async void IntegrationTest()
{
var client = new HttpClient();
var model = new Model();
var result = await client.PostAsync(_url, new StringContent(JsonConvert.SerializeObject(model)));
var expectedModel = JsonConvert.DeserializeObject<Model>(await result.Content.ReadAsStringAsync());
var response = await client.GetAsync($"{_url}/{expectedModel.Id}");
var actualModel = JsonConvert.DeserializeObject<Model>(await result.Content.ReadAsStringAsync());
Assert.Equal(expectedModel.Id, actualModel.Id);
Assert.Equal(expectedModel.Name, actualModel.Name);
}
The SUT for the test above is the whole journey of a request in a web service (Controller, Service, Repository and Database). Depending on our assertions we can catch a potential issue in all layers of this web service.
Here is how a Unit test might look for Controller in a web service:
[Fact]
public async void UnitTest()
{
var serviceMock = new Mock<IService>();
serviceMock.Setup(p => p.MyServiceMethod()).Returns(true);
var controller = new MyController(serviceMock);
var model = new Model();
var expectedModel = controller.MyControllerMethod(model);
Assert.Equal(1, expectedModel.Id);
Assert.Equal("Expected Name", expectedModel.Name);
}
The SUT for the test above is one layer (Controller):
As we can see, Integration tests cover wider SUT than Unit tests with similar amount of code.
Bottom Line
Writing a proper Integration is challenging as it requires initial set up. Yet it pays off with time. Invest your time at the beginning and get a sense of stability about your code later.
Here is how you can ensure you’re writing an Integration test:
🗄️ Use a test instance of database, a test tenant in an external dependency etc.
🖥️ Use test servers instead of mocking and stabbing.
🐳 Use Docker for easier dependency management.
Resources
- My example of an Integration test. Refer to the README for instructions of how to run it.
- I've discovered a nice Diagram editor: Mermaid digram editor.
Posted on May 4, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.