Common First-Time Mistakes in Writing Unit Tests

Muhammad Rafif Murazza
3 min readNov 8, 2022

--

This post is a continuation of the previous post here, the general list of contents are:

  1. Preparing Input & Expected output, & Assertion
  2. Mocking
  3. Mock Static
  4. Making Test Cases & Improving Test Coverage
  5. Common first-time mistakes

Please note that this code will be quite technical & consist of many code examples.

Creating constant reusable dummy value then it being used in tests that has object mutation and running the tests collectively.

In bigger codebases, writing dummies input & expected will take most part of your test codes. There will be tendencies to reuse frequent dummies object. Be careful when you do this.

Let’s say a lot of your test cases need dummy user object, and then you decided to init userMock object once and reuse it across those test cases. You should be aware where you use/put your userMock. If your test code consist of mutating the userMock, you might not want to reuse userMock here. Because, when userMock is used in that test and then being reused in other test, the value is already different from one defined before. It will be fine if you run just that one test case, but if you run it collectively with other test cases, it will most likely break the rest of the test case scenarios.

In case of test case with mutation, code duplication is more preferable to keep test case expectation clear & readable.

Chaining Stubs method

I find, for first timer, chaining method stubbing hard to understand. When stubbing methods, we should be aware in what state your object will be when passed as arguments into the functions you want to stub.

additional example function in UserService.java

Using the example from the screenshot above, we see that someFunction(user) have 2 external calls that are dependent, repo.Persist and dummyServices.GenerateSomeString. We need to be aware that:

  • The user object from the arguments in line 36,
  • The user object passed to repo.Persist(user) in line 42, and
  • The user object used in dummyServices.generateSomeString(user) in line 44

those 3 are all different user objects. So, when writing the test we need to prepare 3 different user dummies object.

unit test code for someFuction() in UserServiceTest.java

Based on previous example, screenshot above is how the unit test code would look like. We can see that for the first user used in UserService.java line 36, we provide with UserTestVariable.VALID_USER which is ID & timestamp still null. For the second user used in UserService.java line 42, we provide with UserTestVariable.VALID_USER_WITH_TS which its ID is null but its timestamp is filled with MOCK_DATE. Lastly, the user used in UserService.java line 44, we provide with UserTestVariable.VALID_FULL which its ID filled with MOCK_DATE.

GitHub Repo for use case example used in this post can be accessed here : mrmurazza/practice-unit-test (github.com). *For now only Go & Java example there, might add more language example in the future.

I hope I explain stuff clearly enough for the readers to understand. If you found any mistake or anything that I missed please do tell me. Any kind of feedbacks or things to discuss are very welcome.

I hope this post will be somewhat useful to anyone out there. 😁

--

--