Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jurabek/golang-table-tests-with-testify-mock
This repo shows how to test and mock multiple dependencies using table-driven tests with testify-mock in Golang
https://github.com/jurabek/golang-table-tests-with-testify-mock
best-practices golang mock table-testing tdd testify testify-mocking unit-testing unittesting
Last synced: about 3 hours ago
JSON representation
This repo shows how to test and mock multiple dependencies using table-driven tests with testify-mock in Golang
- Host: GitHub
- URL: https://github.com/jurabek/golang-table-tests-with-testify-mock
- Owner: jurabek
- License: mit
- Created: 2021-03-11T10:48:40.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2021-03-23T10:58:01.000Z (over 3 years ago)
- Last Synced: 2024-02-29T07:34:34.617Z (8 months ago)
- Topics: best-practices, golang, mock, table-testing, tdd, testify, testify-mocking, unit-testing, unittesting
- Language: Go
- Homepage:
- Size: 15.6 KB
- Stars: 13
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# golang-table-tests-with-testify-mock
This repo shows how to test and mock multiple dependencies using table-driven tests with testify-mock in Golang## Problem
In unit testing and mocking world we need to mock multiple dependencies for specific test cases, (e.g) imagine we have a `struct MacBook` and it depends on `CPU`, `GPU` and `RAM` and we have a `Diagnose` method that returns an error if some of the dependencies `used resources` hits the threshold.
```
type MacBook struct {
cpu cpu.CPU
gpu gpu.GPU
memory memory.RAM
}func (m *MacBook) Diagnose(cpuThreshold, gpuThreshold, memoryThreshold int) error {
if (m.cpu.Usage()) > cpuThreshold {
return CpuUtilizationError
}if m.gpu.Usage() > gpuThreshold {
return GpuUsageError
}if m.memory.FreeMemory() <= memoryThreshold {
return MemoryUsageError
}return nil
}
```
example above we have 3 if conditions, in order to test and get happy result that returns no error, we should have to write at least 4 unit tests or more and mock all dependencies.## Solution
```
func TestMacbookDiagnose(t *testing.T) {
type depFields struct {
cpu *mockedCPU
gpu *mockedGPU
memory *mockedRAM
}type args struct {
cpuThreshold, gpuThreshold, memoryThreshold int
}tests := []struct {
name string
in *args
out erroron func(*depFields)
assert func(*depFields)
}{
// Test cases...
{
name: "when all thresholds not hit return nil",
in: &args{50, 90, 1000},
out: nil,
on: func(df *depFields) {
df.cpu.On("Usage").Return(40) // 40% CPU usage less than cpuThreshold
df.gpu.On("Usage").Return(50) // 50% gpu usage less than gpuThreshold
df.memory.On("FreeMemory").Return(2000) // 2000 MB free memory left so it is larger than 1000 mb threshold
},
assert: func(t *testing.T, df *depFields) {
df.cpu.AssertNumberOfCalls(t, "Usage", 1)
df.gpu.AssertNumberOfCalls(t, "Usage", 1)
df.memory.AssertNumberOfCalls(t, "FreeMemory", 1)
},
},
}
```
basically in the table-driven testing we will define slice of structs that represents test cases, in the example above we have struct that contains callback functions `on: func(*depFields)` and `assert: func(*testing.T, *depFields)` when we call those methods `type depFields struct{}` will be passed into it in order to `mock` or `assert`
```
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// arrange
f := &depFields{
&mockedCPU{},
&mockedGPU{},
&mockedRAM{},
}
mb := NewMacBook(f.cpu, f.gpu, f.memory)
if tt.on != nil {
tt.on(f)
}
// act
err := mb.Diagnose(tt.in.cpuThreshold, tt.in.gpuThreshold, tt.in.memoryThreshold)// assert
if err != tt.out {
t.Errorf("got %v, want %v", err, tt.out)
}
if tt.assert != nil {
tt.assert(t, f)
}
})
}
```example above we are iterating all test cases and running sub tests, on each case we creating `f := &depFields{}` of mocks and passing it onto `on` function to prepare mocks, at the end of the test we also checking `assertion` of mock calls, this helps us to assert number of calls that mocked methods are called inside the `Diagnose` method.
## Links to read
[Table-Driven tests in Go](https://github.com/golang/go/wiki/TableDrivenTests)[Testify Mocking](https://github.com/stretchr/testify#mock-package)