Sitemap
Ciizo

Ciizo

My Tech Journal

Software Testing • Unit Test

3 min readOct 29, 2023

--

I’d like to share my approach to implementing unit tests in a .NET 6 API project, as it works very well. The content will be organized as What Why and How. This information will be valuable even if you’re not working with C# and .NET

What Concepts

These are concepts in my focus on unit tests.

  • Keep tests short, stateless, and scope just one thing (SRP)
  • Executable documents
  • Isolated and Repeatable tests
  • Solitary or Sociable tests
  • Write test before fixing bug
  • Good production code
  • Team standard convention

I will say a bit on Solitary or Sociable, you have to choose carefully, it’s tradeoffs. I prefer solitary for unit tests as much as possible because it’s easy to maintain even when you refactor your code, except when rewriting the code because you might need to update mocks.

For sociable, it should be integration tests. There are some information say sociable is better because less effort to write tests or doesn’t need to update many tests when changing production codes, indeed it’s easy when done in the right way with more effort(than not doing) but good for long term.

Why Do We Need

First, my project already has unit tests, integration tests, and contract tests but I can smell the mess of it. It’s time to improve, but this story will cover only unit tests.

There are two primary needs

  • Creating executable documentations
  • Assistance in identifying poor-quality production code.

With many contributors involved in this project, I hope that everyone focuses not only on writing complex or big test cases but also on producing good quality production code.

If the arrange logic is complex or too big, it might be a sign that there’s something wrong with the production code design itself.

How to Write

In general, the things I do are

  • Use Bogus faker to generate happy model arrangement. In the specific test case, internally reconfigure certain properties in the arrangement. Must declare rules for all properties and be cautious about using random values. Avoid sharing the Faker instance, as it could compromise test isolation and repeatability.”
[Test]
pubic async Task Method_Condition_Expectation()
{
// Arrange
var model = ModelFaker.Generate();
model.SomeProp = "wrong value";
...
}
  • Use AI to generate logical test cases and test names and add business cases by yourself. Also, Use it wisely and carefully.
  • Use the static method or helper class directly within the test case of other method and write test specifically for the static method in a separate file
  • When declaring the expected result that relies on a static method, create a separate test class for the static method. Then, simply call the static method within your expected result declaration.
var expected = new ExampleDto
{
ExampleProp = ExampleStaticClass.ExampleStaticMethod(xx,yy),
};

Next, let’s see how to deal with each type of methods.

Get Ciizo’s stories in your inbox

Join Medium for free to get updates from this writer.

Private method

  • Don’t separate test files, let’s test via the public method that consumes it.
  • If it is complex or has good reason to test it, move it to new public class because that sounds like it should have its own problem domain.
  • When it is utilized by many other methods, seems it’s not private anymore. Make it public and test.

Static method

  • Always test it. It should be solitary tests because the static method can be consumed by many codes.
  • As static, the method should be Pure Function, so it makes sense to have its own test.
  • Don’t create an interface or wrapper class for static methods just to make it able to do Test Double because it requires modifying production code. Imagine having many static classes.

Main method

  • As mentioned in the What section, I prefer solitary and if it is a very complex or big test case like an orchestrator, just write only some happy or critical cases at integration tests.
  • Create a test case that verifies whether all properties of the response model can be set values and returned accurately.
  • Create just a few big test cases so don’t worry about too many Test Double when rewriting some path of the code.

Sub method

  • As it is consumed by the main method, I prefer solitary too.
  • I like to have many sub-methods to make the unit tests to fulfill the concepts mentioned in What section.

--

--