Unit Tests & Test Doubles

It is common that people assume a unit test is done to find bug within the code; well that is not 100% wrong, Unit test done to test the functionality of the code to check whether or not the code is working & deliver as expected. When writing unit test you do not have to create a test cases for everything but to focus on testing that affect behavior of the system.

Unit test are typically came in a form of automated test, inside the automated test; a unit testing script will be written in a strict manner to satisfy a ‘contract’ that will decide the code is delivering correctly or not. There are many testing framework that can be used to create an automated test such as: JUnit in Java, unittest in Python, Mocha in JavaScript and even in language like Go unit test are came within the Standard Library.

Unit Test are proven to be beneficial in a SLDC process, by doing unit test we could get some benefits such as :

  1. Improve code quality
  2. Less bugs, detect bugs earlier.
  3. Provides more reliable and reusable code
  4. It allows for developer to refactor code with ease since by having unit test there are clear set of deliverable.

What is Unit in Unit Test?

As the name suggest an unit test are performed in ‘unit’, a unit can be defined as an individual function, a group of function, an entire class, an individual method, or some even refer unit as 1..n lines of codes. So deciding what is an ‘unit’ in unit testing will entirely depend on you and your team.

In a scenario where I use MVC + Service Layer pattern to develop an API i would usually create unit tests within service layer.

One important thing that you should keep in mind when picking a unit is that, you need to make sure that the unit is capable of executing independently. what does this mean? Cited from here, a test is not a unit test if :

  1. It talks to the database
  2. It communicate across the network
  3. It can’t run correctly at the same time as any of your other unit test.
  4. You have to do special things to your environment.

So how the heck we test something that require a databases? we use Test Doubles

Test Doubles: Mocks, Fakes & Stubs

Test doubles are technique that is used in condition where the unit to be tested require external dependencies such as DB, Network Connection, Library, API, etc.

Fakes

Fakes are objects that have working implementations, but not same as production one. Usually they take some shortcut and have simplified version of production code.

Example of Fake

Example of fake is that instead of using an actual databases instead we use in memory database to store and return simple data, this will allow to do integration test of services without a running database.

Or in a scenario that you should test your code in a server, you could simply run a local server and test the code against the local server.

Stubs

image-20211014213501957

Stub is an object that holds predefined data and uses it to answer calls during tests. It is used when we cannot or don’t want to involve objects that would answer with real data or have undesirable side effects.

An example can be an object that needs to grab some data from the database to respond to a method call. Instead of the real object, we introduced a stub and defined what data should be returned.

Stubs are used to generate a predefined output, in example above stubs are used to generate return from the Socket.Connect() this stub will return a success, failure or an exception this can be used to :

  1. Check the behavior of code under certain return scenario.
  2. To give a consistent return.
  3. To test even the component is not ready.

Mock

image-20211014212907083

Mocks are objects that register calls they receive. In test assertion we can verify on Mocks that all expected actions were performed. We use mocks when we don’t want to invoke production code or when there is no easy way to verify, that intended code was executed. There is no return value and no easy way to check system state change. An example can be a functionality that calls e-mail sending service.

Mock can be used to replace external interface, rather than connecting to the actual API we could just Mock the connection and return the expected result. But bear in mind that mock are not used to check a function behavior or return of values from the function call. it is used to :

  1. Checking the function is called or not

In example above the mock are used to check wether or not MyFunction() called Mock Socket.Connect() or not.

  1. To check how many times does it called?

  2. To check passed paramters.

Simply mock are used to check whether or not your function : Does the right call, in right number of times, with the right parameters.

AAA Pattern

AAA stands for Arrange - Act - Assert

image-20211014204846804

AAA Pattern is a pattern for structuring test, it breakdowns test into three parts :

  1. Arrange

    Usually arrange are used to prepare values to be processed in tests

  2. Act

    Values that are prepared in the arrange will be processed here

  3. Assert

    And finally the processed value will be ‘asserted’ or ‘tested’ to check if it delivers the correct thing.

Sources

  1. https://www.youtube.com/watch?v=NPp2pvhGbkM
  2. https://www.blinkingcaret.com/2016/04/27/what-exactly-is-a-unit-in-unit-testing/
  3. https://medium.com/hardwareandro/what-is-unit-testing-435e8134b16e
  4. https://blog.pragmatists.com/test-doubles-fakes-mocks-and-stubs-1a7491dfa3da
  5. https://medium.com/tunaiku-tech/unit-test-in-golang-57a2a896d90d
  6. https://www.guru99.com/unit-testing-guide.html
  7. https://blog.pragmatists.com/test-doubles-fakes-mocks-and-stubs-1a7491dfa3da