While writing unit test for a method in go, I am stumped at a problem. First, code snippet under test:
func MehodToBeTested(e Entity) {
go saveAudit(e)
//do something on which assertions can be done
}
Entity can be mocked. in the saveAudit method, Entity.Save method is called. In my UT, i want to assert that Entity.Save method is called once. Following is my current UT :
func TestMethod(t *testing.T) {
var mock = &mockEntity{}
mock.On("Save").Return(nil)
//make call to func under test
MethodToBeTested(mock)
// Assert that Save is called on Entity
mock.AssertNumberOfCalls(t, "Save",1)
}
This is giving error saying : Expected number of calls (1) does not match the actual number of calls (0) since the actual call is happening in another go routine. How can i test this?
I use the same technique. Just wait for goroutine end. Very likely it’s not yet set.
Also, I recommend to run such tests with the race-condition detector. It helps to catch such situations. Then you can add some synchronization to the tests to make them reliable.
Example from my test. A tested function should check in parallel that both web pages contain the specified string. So test should check that tested function has visited both pages
UPDATE: incorrect test was attached. Fixed.
func TestCheckSites_TwoSlowHandlers_BothContain(t *testing.T) {
var config = GetConfig()
var v1, v2 bool
var wg sync.WaitGroup
wg.Add(2)
handler1 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer wg.Done()
v1 = true
time.Sleep(2 * config.Http.Timeout) // Use double HTTP_TIMEOUT
io.WriteString(w, "Present")
})
ts1 := httptest.NewServer(handler1)
defer ts1.Close()
handler2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer wg.Done()
v2 = true
time.Sleep(2 * config.Http.Timeout)
io.WriteString(w, "Present")
})
ts2 := httptest.NewServer(handler2)
defer ts2.Close()
result, err := checkSites([]string{ts1.URL, ts2.URL}, "Present")
assert.Equal(t, nil, err, "Error should be nil")
assert.Contains(t, []string{""}, result, "Should be empty string")
//assert.(t, ts1.URL, result, "Should first or second empty string")
wg.Wait()
assert.Equal(t, true, v1, "First server should be visited")
assert.Equal(t, true, v2, "Second server should be visited")
}