Skip to content

Commit

Permalink
feat: add argument storage (#59)
Browse files Browse the repository at this point in the history
Signed-off-by: tkrop <[email protected]>
  • Loading branch information
tkrop committed Nov 16, 2023
1 parent 665c1b8 commit 2e729aa
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 4 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,10 @@ func TestUnit(t *testing.T) {
Run(func(t test.Test, param UnitParams){

// Given
mocks := mock.NewMock(t).Expect(
param.mockSetup,
)
mocks := mock.NewMock(t).
SetArg("common-url", "http://test").Expect(
param.mockSetup,
)

unit := NewUnitService(
mock.Get(mocks, NewServiceMock),
Expand Down
8 changes: 7 additions & 1 deletion mock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func TestUnit(t *testing.T) {
mocks := mock.NewMocks(t)

mockSetup := mock.Get(mocks, NewServiceMock).EXPECT()...

mocks.Expect(mockSetup)

service := NewUnitService(
Expand Down Expand Up @@ -85,11 +86,16 @@ prepared to handle tests with detached *goroutines*, i.e. functions that are
spawned by the system-under-test without waiting for their result.

The mock handler therefore provides a `WaitGroup` and automatically registers
a single mock call on each request using `mocks.Do(...)` and notifies the
a single mock call on each request using `mocks.Do(...)` to notify the call
completion via `Do|DoAndReturn()`. For test with detached *goroutines* the
test can wait via `mocks.Wait()`, before finishing and checking whether the
mock calls are completely consumed.

Since some arguments needed to setup a mock call may only be available after
creating the test runner, the mock controller provides a dynamic key-value
storage that is accessible via `SetArg(key,value)`, `SetArgs(map[key]value)`,
and `GetArg(key)`.

**Note:** Since waiting for mock calls can take literally for ever in case of
test failures, it is advised to use an isolated [test environment](../test)
that unlocks the waiting test in case of failures and fatal errors, e.g.
Expand Down
25 changes: 25 additions & 0 deletions mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ type Mocks struct {
wg sync.WaitGroup
// The map of mock singletons.
mocks map[reflect.Value]any
// A map of mock key value pairs.
args map[any]any
}

// NewMocks creates a new mock handler using given test reporter, e.g.
Expand All @@ -90,6 +92,7 @@ func NewMocks(t gomock.TestReporter) *Mocks {
Ctrl: gomock.NewController(t),
wg: sync.NewLenientWaitGroup(),
mocks: map[reflect.Value]any{},
args: map[any]any{},
}).syncWith(t)
}

Expand All @@ -116,6 +119,28 @@ func (mocks *Mocks) Expect(fncalls SetupFunc) *Mocks {
return mocks
}

// GetArg gets the mock argument value for the given argument key. This can be
// used to access a common test arguments from a mock call.
func (mocks *Mocks) GetArg(key any) any {
return mocks.args[key]
}

// SetArg sets the given mock argument value for the given argument key. This
// can be used to pass a common test arguments to mock calls.
func (mocks *Mocks) SetArg(key any, value any) *Mocks {
mocks.args[key] = value
return mocks
}

// SetArgs sets the given mock argument values for the given argument keys.
// This can be used to pass a set of common test arguments to mock calls.
func (mocks *Mocks) SetArgs(args map[any]any) *Mocks {
for key, value := range args {
mocks.args[key] = value
}
return mocks
}

// syncWith used to synchronize the wait group of the mock setup with the wait
// group of the given test reporter. This function is called automatically on
// mock creation and therefore does not need to be called on the same reporter
Expand Down
22 changes: 22 additions & 0 deletions mock/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,28 @@ func TestMocks(t *testing.T) {
})
}

func TestMockArgs(t *testing.T) {
// Given
mocks := mock.NewMocks(t)

// When
mocks.SetArg("a", "a")

// Than
assert.Equal(t, mocks.GetArg("a"), "a")
assert.Equal(t, mocks.GetArg("b"), nil)

// When
mocks.SetArgs(map[any]any{
"a": "b",
"b": "b",
})

// Than
assert.Equal(t, mocks.GetArg("a"), "b")
assert.Equal(t, mocks.GetArg("b"), "b")
}

func MockSetup(t gomock.TestReporter, mockSetup mock.SetupFunc) *mock.Mocks {
return mock.NewMocks(t).Expect(mockSetup)
}
Expand Down

0 comments on commit 2e729aa

Please sign in to comment.