Unit testing is important. That being said, there are a few things about golang that make testing difficult. I am going to try to explain a few mechanisms I use to deal with common unit testing problems in golang:
1.) Monkey Patching Functions For Unit Testing 2.) Mocking Struct Methods via Interfacing
tl;dr: unit testing in golang
My coworker agtorre and I implement our mocking with these mechanisms for our unit testing.
Monkey Patching in Golang
So, from what I understand, monkey patching is the art of modifying a module, or package at runtime to alter the course of execution. To those ends, golang fits this model pretty well, as functions are first class constructs. When we want to make a third party package function “mocked” we can merely do the following:
Since package functions are assignable to variables, we can mock like this:
The following things are happening here:
- When this test is run, we are storing the old location of the mocked function.
- Then we are detering the reset of the old location of the original function back.
- This defer will happen after the function finishes, before the stack is popped.
- Then we are overwriting our sqlOpen package function with a new definition that will throw an error
- Then we run main()
At this point main is run with our fake sqlOpen definition and we should see a panic. This is an ugly, but functional way of testing different potential outcomes of package functions.
Mocking Struct Methods via Interfacing
Go allows for interfaces, which is excellent for making things like other things. We are going to use interface implementations of third party structs to mock out a virtual struct that will allow us to perform mocking of a struct’s methods:
We are tasked with testing the edge case of when Increment returns an error, and we need to test if a panic occurs. To do this we need to mock out Something.Increment and return a non-nil error result. Here is how I usually go about doing this:
Hope this was helpful to anyone.