From 002d3ddef398910d54c3400ffa4e6b26c51be146 Mon Sep 17 00:00:00 2001 From: anastasia Date: Wed, 10 Jan 2018 13:57:46 +1000 Subject: [PATCH 1/3] Add check for calls when order does not matter. --- stub.go | 25 +++++++++++++++++++++++++ stub_test.go | 16 ++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/stub.go b/stub.go index d9f0c97..543c175 100644 --- a/stub.go +++ b/stub.go @@ -9,6 +9,7 @@ import ( jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" + "reflect" ) // StubCall records the name of a called function and the passed args. @@ -193,6 +194,30 @@ 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) { + c.Check(len(f.calls), gc.Equals, len(expected)) + callWasMade := func(call StubCall) bool { + for _, madeCall := range f.calls { + if reflect.DeepEqual(call, madeCall) { + return true + } + } + c.Logf("call [%v] was never made", call) + return false + } + + for _, call := range expected { + if !callWasMade(call) { + c.Fail() + } + } +} + // 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 diff --git a/stub_test.go b/stub_test.go index 44aa160..940cdaf 100644 --- a/stub_test.go +++ b/stub_test.go @@ -430,3 +430,19 @@ 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", + }}) +} From 1e005530b7a548246e10e9a6d6bd2e3db672fc51 Mon Sep 17 00:00:00 2001 From: anastasia Date: Wed, 10 Jan 2018 14:30:42 +1000 Subject: [PATCH 2/3] Group imports correctly. --- stub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stub.go b/stub.go index 543c175..c45350a 100644 --- a/stub.go +++ b/stub.go @@ -5,11 +5,11 @@ package testing import ( "fmt" + "reflect" "sync" jc "github.com/juju/testing/checkers" gc "gopkg.in/check.v1" - "reflect" ) // StubCall records the name of a called function and the passed args. From c4ba17610931a3751dcd36d8384595aacacfcf8f Mon Sep 17 00:00:00 2001 From: anastasia Date: Thu, 11 Jan 2018 09:38:01 +1000 Subject: [PATCH 3/3] Cater for multiple occurence of the same method call. --- stub.go | 19 ++++++++++--------- stub_test.go | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/stub.go b/stub.go index c45350a..12f0fd8 100644 --- a/stub.go +++ b/stub.go @@ -200,22 +200,23 @@ func (f *Stub) CheckCalls(c *gc.C, expected []StubCall) { // 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) { - c.Check(len(f.calls), gc.Equals, len(expected)) - callWasMade := func(call StubCall) bool { - for _, madeCall := range f.calls { + // 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) { - return true + // Remove found call from the copy of all-calls-made collection. + calls = append(calls[:i], calls[i+1:]...) + break } } - c.Logf("call [%v] was never made", call) - return false } for _, call := range expected { - if !callWasMade(call) { - c.Fail() - } + 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 diff --git a/stub_test.go b/stub_test.go index 940cdaf..79f0aae 100644 --- a/stub_test.go +++ b/stub_test.go @@ -446,3 +446,25 @@ func (s *stubSuite) TestMethodCallsUnordered(c *gc.C) { 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") +}