Skip to content

Commit

Permalink
Add CalledAtNWith (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
kasvtv committed Nov 13, 2023
1 parent 4fea348 commit a9ed2f1
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 9 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ The following methods are defined in both packages.
- `NotCalledWith(t, mockFn, msgAndArgs...)`
- `CalledOnceWith(t, mockFn, msgAndArgs...)`
- `CalledNWith(t, mockFn, n, msgAndArgs...)`
- `CalledAtNWith(t, mockFn, n, msgAndArgs...)`

These methods can be used as follows.

Expand Down
6 changes: 6 additions & 0 deletions internal/integration/testify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ func TestTestifyCallsWithVariadicArgs(t *testing.T) {
mockassert.CalledNWith(t, mock.DoArgsFunc, 2, mockassert.Values(
func(v string) bool { return strings.Contains(v, "a") },
))
mockassert.CalledAtNWith(t, mock.DoArgsFunc, 1, mockassert.Values(
func(v string) bool { return strings.Contains(v, "a") },
))
mockassert.CalledAtNWith(t, mock.DoArgsFunc, 2, mockassert.Values(
func(v string) bool { return strings.Contains(v, "a") },
))

// Mismatched variadic arg
mockassert.NotCalledWith(t, mock.DoArgsFunc, mockassert.Values(
Expand Down
4 changes: 2 additions & 2 deletions testutil/assert/asserter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (

// CallInstanceAsserter determines whether or not a set of argument values from a call
// of a mock function match the test constraints of a particular function call. See the
// assertions `CalledWith`, `NotCalledWith`, `CalledOnceWith`, and `CalledNWith` for
// further usage.
// assertions `CalledWith`, `NotCalledWith`, `CalledOnceWith`, `CalledNWith`, and
// `CalledAtNWith` for further usage.
type CallInstanceAsserter interface {
// Assert determines if the given argument values matches the expected
// function call.
Expand Down
28 changes: 23 additions & 5 deletions testutil/assert/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func CalledOnce(t assert.TestingT, mockFn interface{}, msgAndArgs ...interface{}
return CalledN(t, mockFn, 1, msgAndArgs...)
}

// CalledOnce asserts that the mock function object was called exactly n times.
// CalledN asserts that the mock function object was called exactly n times.
func CalledN(t assert.TestingT, mockFn interface{}, n int, msgAndArgs ...interface{}) bool {
callCount, ok := callCount(t, mockFn, msgAndArgs...)
if !ok {
Expand All @@ -59,20 +59,20 @@ func CalledWith(t assert.TestingT, mockFn interface{}, asserter CallInstanceAsse
return false
}
if matchingCallCount == 0 {
return assert.Fail(t, fmt.Sprintf("Expected %T to be called at least once", mockFn), msgAndArgs...)
return assert.Fail(t, fmt.Sprintf("Expected %T to be called with given arguments at least once", mockFn), msgAndArgs...)
}
return true
}

// CalledWith asserts that the mock function object was not called with a set of arguments
// NotCalledWith asserts that the mock function object was not called with a set of arguments
// matching the given call instance asserter.
func NotCalledWith(t assert.TestingT, mockFn interface{}, asserter CallInstanceAsserter, msgAndArgs ...interface{}) bool {
matchingCallCount, ok := callCountWith(t, mockFn, asserter, msgAndArgs...)
if !ok {
return false
}
if matchingCallCount != 0 {
return assert.Fail(t, fmt.Sprintf("Did not expect %T to be called", mockFn), msgAndArgs...)
return assert.Fail(t, fmt.Sprintf("Did not expect %T to be called with given arguments", mockFn), msgAndArgs...)
}
return true
}
Expand All @@ -91,11 +91,29 @@ func CalledNWith(t assert.TestingT, mockFn interface{}, n int, asserter CallInst
return false
}
if matchingCallCount != n {
return assert.Fail(t, fmt.Sprintf("Expected %T to be called exactly %d times, called %d times", mockFn, n, matchingCallCount), msgAndArgs...)
return assert.Fail(t, fmt.Sprintf("Expected %T to be called with given arguments exactly %d times, called %d times", mockFn, n, matchingCallCount), msgAndArgs...)
}
return true
}

// CalledAtNWith asserts that the mock function objects nth call was with a set of
// arguments matching the given call instance asserter.
func CalledAtNWith(t assert.TestingT, mockFn interface{}, n int, asserter CallInstanceAsserter, msgAndArgs ...interface{}) bool {
hist, ok := testutil.GetCallHistory(mockFn)
if !ok {
return false
}
if len(hist) < n {
return assert.Fail(t, fmt.Sprintf("Expected %T to be called at least %d times, called %d times", mockFn, n, len(hist)), msgAndArgs...)
}

if !asserter.Assert(hist[n]) {
return assert.Fail(t, fmt.Sprintf("Expected call %d of %T to be with given arguments", n, mockFn), msgAndArgs...)
}

return true
}

// callCount returns the number of times the given mock function was called.
func callCount(t assert.TestingT, mockFn interface{}, msgAndArgs ...interface{}) (int, bool) {
return callCountWith(t, mockFn, CallInstanceAsserterFunc(func(call interface{}) bool { return true }), msgAndArgs...)
Expand Down
12 changes: 10 additions & 2 deletions testutil/require/require.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func CalledOnce(t require.TestingT, mockFn interface{}, msgAndArgs ...interface{
}
}

// CalledOnce asserts that the mock function object was called exactly n times.
// CalledN asserts that the mock function object was called exactly n times.
func CalledN(t require.TestingT, mockFn interface{}, n int, msgAndArgs ...interface{}) {
if !mockassert.CalledN(t, mockFn, n, msgAndArgs...) {
t.FailNow()
Expand All @@ -41,7 +41,7 @@ func CalledWith(t require.TestingT, mockFn interface{}, asserter CallInstanceAss
}
}

// CalledWith asserts that the mock function object was not called with a set of arguments
// NotCalledWith asserts that the mock function object was not called with a set of arguments
// matching the given mockassertion function.
func NotCalledWith(t require.TestingT, mockFn interface{}, asserter CallInstanceAsserter, msgAndArgs ...interface{}) {
if !mockassert.NotCalledWith(t, mockFn, asserter, msgAndArgs...) {
Expand All @@ -64,3 +64,11 @@ func CalledNWith(t require.TestingT, mockFn interface{}, n int, asserter CallIns
t.FailNow()
}
}

// CalledAtNWith asserts that the mock function objects nth call was with a set of
// arguments matching the given call instance asserter.
func CalledAtNWith(t require.TestingT, mockFn interface{}, n int, asserter CallInstanceAsserter, msgAndArgs ...interface{}) {
if !mockassert.CalledAtNWith(t, mockFn, n, asserter, msgAndArgs...) {
t.FailNow()
}
}

0 comments on commit a9ed2f1

Please sign in to comment.