Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add argument storage (#59) #59

Merged
merged 1 commit into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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