I have an object like this:
type Store struct {
mutex sync.RWMutex
data map[string]int
}
func (s * Store) Read(key string) int, error {
// ...
defer s.mutex.RUnlock()
s.mutex.RLock()
// ...
return val, nil
}
func (s * Store) Write(key string, value int) error {
// ...
defer s.mutex.Unlock()
s.mutex.Lock()
// ...
return nil
}
How should unit-tests to look like for methods Read
& Write
to check that they are thread safe?
I think there are already exists patterns for cases like this, but I didn't find anything.
I read about -race
flag:
the race detector can detect race conditions only when they are actually triggered by running code, which means it's important to run race-enabled binaries under realistic workloads
My question is how to write unit-test which emulates realistic workloads.
Run your tests with the Race detector. In short, run:
go test -race
Or to build a normal binary, such as to run on a staging server, use:
go build -race
But there are many more options, so best to read up on it :)
If your goal is to test under realistic load, your best option is to compile your code with go build -race
, then run it under realistic load. This probably means on a staging server. But don't confuse this with unit testing!
Unit testing is for testing units--small parts of code, usually individual functions. Load/race testing is a different beast, and requires different tools and an entirely different approach.
The fact that Go will easily run unit tests with the race detector is nice, and often catches races. But it will not, nor should not be expected to, catch all races, since the nature of unit test execution is entirely different from that of production execution.