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

Stub check calls without order. #132

Merged
merged 3 commits into from
Jan 15, 2018
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
26 changes: 26 additions & 0 deletions stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package testing

import (
"fmt"
"reflect"
"sync"

jc "github.com/juju/testing/checkers"
Expand Down Expand Up @@ -193,6 +194,31 @@ func (f *Stub) CheckCalls(c *gc.C, expected []StubCall) {
c.Check(f.calls, jc.DeepEquals, expected)
}

// CheckCallsUnordered verifies that the history of calls on the stub's methods
// contains the expected calls. The receivers are not checked. If they
// are significant then check Stub.Receivers separately.
// This method explicitly does not check if the calls were made in order, just
// whether they have been made.
func (f *Stub) CheckCallsUnordered(c *gc.C, expected []StubCall) {
// Take a copy of all calls made to the stub.
calls := f.calls[:]
checkCallMade := func(call StubCall) {
for i, madeCall := range calls {
if reflect.DeepEqual(call, madeCall) {
// Remove found call from the copy of all-calls-made collection.
calls = append(calls[:i], calls[i+1:]...)
break
}
}
}

for _, call := range expected {
checkCallMade(call)
}
// If all expected calls were made, our resulting collection should be empty.
c.Check(calls, gc.DeepEquals, []StubCall{})
}

// CheckCall checks the recorded call at the given index against the
// provided values. If the index is out of bounds then the check fails.
// The receiver is not checked. If it is significant for a test then it
Expand Down
38 changes: 38 additions & 0 deletions stub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,41 @@ func (s *stubSuite) TestCheckNoCalls(c *gc.C) {
c.ExpectFailure(`the "standard" Stub.CheckNoCalls call should fail here`)
s.stub.CheckNoCalls(c)
}

func (s *stubSuite) TestMethodCallsUnordered(c *gc.C) {
s.stub.MethodCall(s.stub, "Method1", 1, 2, 3)
s.stub.AddCall("aFunc", "arg")
s.stub.MethodCall(s.stub, "Method2")

s.stub.CheckCallsUnordered(c, []testing.StubCall{{
FuncName: "aFunc",
Args: []interface{}{"arg"},
}, {
FuncName: "Method1",
Args: []interface{}{1, 2, 3},
}, {
FuncName: "Method2",
}})
}

// This case checks that in the scenario when expected calls are
// [a,b,c,c] but the calls made are actually [a,b,b,c], we fail correctly.
func (s *stubSuite) TestMethodCallsUnorderedDuplicateFail(c *gc.C) {
s.stub.MethodCall(s.stub, "Method1", 1, 2, 3)
s.stub.MethodCall(s.stub, "Method1", 1, 2, 3)
s.stub.AddCall("aFunc", "arg")
s.stub.MethodCall(s.stub, "Method2")

s.stub.CheckCallsUnordered(c, []testing.StubCall{{
FuncName: "aFunc",
Args: []interface{}{"arg"},
}, {
FuncName: "Method1",
Args: []interface{}{1, 2, 3},
}, {
FuncName: "Method2",
}, {
FuncName: "Method2",
}})
c.ExpectFailure("should have failed as expected calls differ from calls made")
}