github.com/petergtz/pegomock@v2.9.1-0.20230424204322-eb0e044013df+incompatible/dsl_test.go (about)

     1  // Copyright 2015 Peter Goetz
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package pegomock_test
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"net/http"
    21  	"reflect"
    22  	"sync"
    23  	"testing"
    24  	"time"
    25  
    26  	. "github.com/petergtz/pegomock"
    27  	. "github.com/petergtz/pegomock/matchers"
    28  
    29  	"github.com/onsi/ginkgo"
    30  	"github.com/onsi/gomega"
    31  	"github.com/petergtz/pegomock"
    32  	"github.com/petergtz/pegomock/test_interface"
    33  )
    34  
    35  var (
    36  	BeforeEach       = ginkgo.BeforeEach
    37  	It               = ginkgo.It
    38  	FIt              = ginkgo.FIt
    39  	Describe         = ginkgo.Describe
    40  	Context          = ginkgo.Context
    41  	BeNil            = gomega.BeNil
    42  	BeTrue           = gomega.BeTrue
    43  	ConsistOf        = gomega.ConsistOf
    44  	ContainSubstring = gomega.ContainSubstring
    45  	MatchError       = gomega.MatchError
    46  	Equal            = gomega.Equal
    47  	Expect           = gomega.Expect
    48  	HaveLen          = gomega.HaveLen
    49  	HavePrefix       = gomega.HavePrefix
    50  	Panic            = gomega.Panic
    51  	SatisfyAll       = gomega.SatisfyAll
    52  )
    53  
    54  var checkThatInterfaceIsImplemented test_interface.Display = NewMockDisplay()
    55  
    56  func TestDSL(t *testing.T) {
    57  	gomega.RegisterFailHandler(ginkgo.Fail)
    58  	pegomock.RegisterMockFailHandler(func(message string, callerSkip ...int) { panic(message) })
    59  	ginkgo.RunSpecs(t, "DSL Suite")
    60  }
    61  
    62  func AnyError() error {
    63  	RegisterMatcher(NewAnyMatcher(reflect.TypeOf((*error)(nil)).Elem()))
    64  	return nil
    65  }
    66  
    67  func AnyRequest() http.Request {
    68  	RegisterMatcher(NewAnyMatcher(reflect.TypeOf((*http.Request)(nil)).Elem()))
    69  	return http.Request{}
    70  }
    71  
    72  func AnyRequestPtr() *http.Request {
    73  	RegisterMatcher(NewAnyMatcher(reflect.TypeOf((**http.Request)(nil)).Elem()))
    74  	return nil
    75  }
    76  
    77  type NeverMatcher struct{}
    78  
    79  func (matcher *NeverMatcher) Matches(param Param) bool { return false }
    80  func (matcher *NeverMatcher) FailureMessage() string {
    81  	return "This matcher never matches (and is only for testing purposes)"
    82  }
    83  func (matcher *NeverMatcher) String() string { return "NeverMatching" }
    84  
    85  func NeverMatchingRequest() http.Request {
    86  	RegisterMatcher(&NeverMatcher{})
    87  	return http.Request{}
    88  }
    89  
    90  var _ = Describe("MockDisplay", func() {
    91  	var display *MockDisplay
    92  
    93  	BeforeEach(func() {
    94  		display = NewMockDisplay()
    95  	})
    96  
    97  	Context("Calling SomeValue() with no stubbing", func() {
    98  		It("returns zero value", func() {
    99  			Expect(display.SomeValue()).To(Equal(""))
   100  		})
   101  	})
   102  
   103  	Context("Stubbing MultipleParamsAndReturnValue() with matchers", func() {
   104  		BeforeEach(func() {
   105  			When(display.MultipleParamsAndReturnValue(EqString("Hello"), EqInt(333))).ThenReturn("Bla")
   106  		})
   107  
   108  		It("fails during verification when mock was not called", func() {
   109  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("Hello", 333) }).To(PanicWithMessageTo(HavePrefix(
   110  				"Mock invocation count for MultipleParamsAndReturnValue(\"Hello\", 333) does not match expectation.\n\n\tExpected: 1; but got: 0",
   111  			)))
   112  		})
   113  
   114  		It("succeeds verification when mock was called", func() {
   115  			display.MultipleParamsAndReturnValue("Hello", 333)
   116  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("Hello", 333) }).NotTo(Panic())
   117  		})
   118  
   119  		It("succeeds verification when verification and invocation are mixed", func() {
   120  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("Hello", 333) }).To(PanicWithMessageTo(HavePrefix(
   121  				expectation{method: "MultipleParamsAndReturnValue(\"Hello\", 333)", expected: "1", actual: "0"}.string(),
   122  			)))
   123  			display.MultipleParamsAndReturnValue("Hello", 333)
   124  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("Hello", 333) }).NotTo(Panic())
   125  		})
   126  	})
   127  
   128  	Context("Calling MultipleParamsAndReturnValue() with \"Any\"-matchers", func() {
   129  		It("succeeds all verifications that match", func() {
   130  			When(display.MultipleParamsAndReturnValue(AnyString(), EqInt(333))).ThenReturn("Bla")
   131  
   132  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("Hello", 333) }).To(PanicWithMessageTo(HavePrefix(
   133  				expectation{method: "MultipleParamsAndReturnValue(\"Hello\", 333)", expected: "1", actual: "0"}.string(),
   134  			)))
   135  
   136  			display.MultipleParamsAndReturnValue("Hello", 333)
   137  			display.MultipleParamsAndReturnValue("Hello again", 333)
   138  			display.MultipleParamsAndReturnValue("And again", 333)
   139  
   140  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("Hello", 333) }).NotTo(Panic())
   141  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("Hello again", 333) }).NotTo(Panic())
   142  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("And again", 333) }).NotTo(Panic())
   143  
   144  			Expect(func() { display.VerifyWasCalledOnce().MultipleParamsAndReturnValue("And again", 444) }).To(PanicWithMessageTo(HavePrefix(
   145  				expectation{method: "MultipleParamsAndReturnValue(\"And again\", 444)", expected: "1", actual: "0"}.string(),
   146  			)))
   147  
   148  		})
   149  	})
   150  
   151  	Context("Calling MultipleParamsAndReturnValue() only with matchers on some parameters", func() {
   152  		It("panics", func() {
   153  			Expect(func() { When(display.MultipleParamsAndReturnValue(EqString("Hello"), 333)) }).To(PanicWithMessageTo(HavePrefix(
   154  				"Invalid use of matchers!\n\n 2 matchers expected, 1 recorded.\n\n" +
   155  					"This error may occur if matchers are combined with raw values:\n" +
   156  					"    //incorrect:\n" +
   157  					"    someFunc(AnyInt(), \"raw String\")\n" +
   158  					"When using matchers, all arguments have to be provided by matchers.\n" +
   159  					"For example:\n" +
   160  					"    //correct:\n" +
   161  					"    someFunc(AnyInt(), EqString(\"String by matcher\"))",
   162  			)))
   163  		})
   164  	})
   165  
   166  	Context("Stubbing with consecutive return values", func() {
   167  		BeforeEach(func() {
   168  			When(display.SomeValue()).ThenReturn("Hello").ThenReturn("again")
   169  		})
   170  
   171  		It("returns stubbed values when calling mock", func() {
   172  			Expect(display.SomeValue()).To(Equal("Hello"))
   173  			Expect(display.SomeValue()).To(Equal("again"))
   174  		})
   175  
   176  		It("returns last stubbed value repeatedly", func() {
   177  			Expect(display.SomeValue()).To(Equal("Hello"))
   178  			Expect(display.SomeValue()).To(Equal("again"))
   179  			Expect(display.SomeValue()).To(Equal("again"))
   180  			Expect(display.SomeValue()).To(Equal("again"))
   181  			Expect(display.SomeValue()).To(Equal("again"))
   182  			Expect(display.SomeValue()).To(Equal("again"))
   183  		})
   184  
   185  		It("can be verified that mock was called", func() {
   186  			display.SomeValue()
   187  			Expect(func() { display.VerifyWasCalledOnce().SomeValue() }).NotTo(Panic())
   188  		})
   189  
   190  		It("fails if verify is called on mock that was not invoked.", func() {
   191  			Expect(func() { display.VerifyWasCalledOnce().Show("Some parameter") }).To(PanicWithMessageTo(HavePrefix(
   192  				expectation{method: "Show(\"Some parameter\")", expected: "1", actual: "0"}.string(),
   193  			)))
   194  		})
   195  
   196  		It("fails if verify is called on mock that was invoked more than once.", func() {
   197  			display.Show("param")
   198  			display.Show("param")
   199  			Expect(func() { display.VerifyWasCalledOnce().Show("param") }).To(PanicWithMessageTo(HavePrefix(
   200  				expectation{method: "Show(\"param\")", expected: "1", actual: "2"}.string(),
   201  			)))
   202  
   203  		})
   204  	})
   205  
   206  	Context("Stubbing with invalid return type", func() {
   207  		It("panics", func() {
   208  			Expect(func() { When(display.SomeValue()).ThenReturn("Hello").ThenReturn(0) }).To(PanicWithMessageTo(HavePrefix(
   209  				"Return value of type int not assignable to return type string",
   210  			)))
   211  		})
   212  	})
   213  
   214  	Describe("https://github.com/petergtz/pegomock/issues/24", func() {
   215  		Context("Stubbing with nil value", func() {
   216  			It("does not panic when return type is interface{}", func() {
   217  				When(display.InterfaceReturnValue()).ThenReturn(nil)
   218  				Expect(display.InterfaceReturnValue()).To(BeNil())
   219  			})
   220  
   221  			It("does not panic when return type is error interface", func() {
   222  				When(display.ErrorReturnValue()).ThenReturn(nil)
   223  				Expect(display.ErrorReturnValue()).To(BeNil())
   224  			})
   225  		})
   226  
   227  		Context("Stubbing with value that implements interface{}", func() {
   228  			It("does not panic", func() {
   229  				When(display.InterfaceReturnValue()).ThenReturn("Hello")
   230  				Expect(display.InterfaceReturnValue()).To(Equal("Hello"))
   231  			})
   232  		})
   233  
   234  		Context("Stubbing with value that implements error interface", func() {
   235  			It("does not panic", func() {
   236  				When(display.ErrorReturnValue()).ThenReturn(errors.New("Ouch"))
   237  				Expect(display.ErrorReturnValue()).To(Equal(errors.New("Ouch")))
   238  			})
   239  		})
   240  
   241  		Context("Stubbing with value that does not implement error interface", func() {
   242  			It("panics", func() {
   243  				Expect(func() { When(display.ErrorReturnValue()).ThenReturn("Blub") }).To(PanicWithMessageTo(HavePrefix(
   244  					"Return value of type string not assignable to return type error",
   245  				)))
   246  			})
   247  		})
   248  
   249  		Context("Stubbing string return type with nil value", func() {
   250  			It("panics", func() {
   251  				Expect(func() { When(display.SomeValue()).ThenReturn(nil) }).To(PanicWith(
   252  					"Return value 'nil' not assignable to return type string",
   253  				))
   254  			})
   255  		})
   256  
   257  	})
   258  
   259  	Context("Stubbed method, but no invocation takes place", func() {
   260  		It("fails during verification", func() {
   261  			When(display.SomeValue()).ThenReturn("Hello")
   262  			Expect(func() { display.VerifyWasCalledOnce().SomeValue() }).To(PanicWithMessageTo(HavePrefix(
   263  				expectation{method: "SomeValue()", expected: "1", actual: "0"}.string(),
   264  			)))
   265  		})
   266  	})
   267  
   268  	Context("Calling Flash() with specific arguments", func() {
   269  
   270  		BeforeEach(func() { display.Flash("Hello", 333) })
   271  
   272  		It("succeeds verification if values are matching", func() {
   273  			Expect(func() { display.VerifyWasCalledOnce().Flash("Hello", 333) }).NotTo(Panic())
   274  		})
   275  
   276  		It("fails during verification if values are not matching", func() {
   277  			Expect(func() { display.VerifyWasCalledOnce().Flash("Hello", 666) }).To(PanicWithMessageTo(HavePrefix(
   278  				expectation{method: "Flash(\"Hello\", 666)", expected: "1", actual: "0"}.string(),
   279  			)))
   280  		})
   281  
   282  		It("succeeds during verification when using Any-matchers ", func() {
   283  			Expect(func() { display.VerifyWasCalledOnce().Flash(AnyString(), AnyInt()) }).NotTo(Panic())
   284  		})
   285  
   286  		It("succeeds during verification when using valid Eq-matchers ", func() {
   287  			Expect(func() { display.VerifyWasCalledOnce().Flash(EqString("Hello"), EqInt(333)) }).NotTo(Panic())
   288  		})
   289  
   290  		It("fails during verification when using invalid Eq-matchers ", func() {
   291  			Expect(func() { display.VerifyWasCalledOnce().Flash(EqString("Invalid"), EqInt(-1)) }).To(PanicWithMessageTo(HavePrefix(
   292  				expectation{method: `Flash(Eq("Invalid"), Eq(-1))`, expected: "1", actual: "0"}.string(),
   293  			)))
   294  		})
   295  
   296  		It("fails when not using matchers for all params", func() {
   297  			Expect(func() { display.VerifyWasCalledOnce().Flash("Hello", AnyInt()) }).To(PanicWith(
   298  				"Invalid use of matchers!\n\n 2 matchers expected, 1 recorded.\n\n" +
   299  					"This error may occur if matchers are combined with raw values:\n" +
   300  					"    //incorrect:\n" +
   301  					"    someFunc(AnyInt(), \"raw String\")\n" +
   302  					"When using matchers, all arguments have to be provided by matchers.\n" +
   303  					"For example:\n" +
   304  					"    //correct:\n" +
   305  					"    someFunc(AnyInt(), EqString(\"String by matcher\"))",
   306  			))
   307  		})
   308  	})
   309  
   310  	Describe("Invocation count matching", func() {
   311  
   312  		Context("Calling Flash() twice", func() {
   313  
   314  			BeforeEach(func() {
   315  				display.Flash("Hello", 333)
   316  				display.Flash("Hello", 333)
   317  			})
   318  
   319  			It("succeeds verification if verifying with Times(2)", func() {
   320  				Expect(func() { display.VerifyWasCalled(Times(2)).Flash("Hello", 333) }).NotTo(Panic())
   321  			})
   322  
   323  			It("fails during verification if verifying with VerifyWasCalledOnce", func() {
   324  				Expect(func() { display.VerifyWasCalledOnce().Flash("Hello", 333) }).To(PanicWithMessageTo(HavePrefix(
   325  					expectation{method: "Flash(\"Hello\", 333)", expected: "1", actual: "2"}.string(),
   326  				)))
   327  			})
   328  
   329  			It("fails during verification if verifying with Times(1)", func() {
   330  				Expect(func() { display.VerifyWasCalled(Times(1)).Flash("Hello", 333) }).To(PanicWithMessageTo(HavePrefix(
   331  					expectation{method: "Flash(\"Hello\", 333)", expected: "1", actual: "2"}.string(),
   332  				)))
   333  			})
   334  
   335  			It("succeeds during verification when using AtLeast(1)", func() {
   336  				Expect(func() { display.VerifyWasCalled(AtLeast(1)).Flash("Hello", 333) }).NotTo(Panic())
   337  			})
   338  
   339  			It("succeeds during verification when using AtLeast(2)", func() {
   340  				Expect(func() { display.VerifyWasCalled(AtLeast(2)).Flash("Hello", 333) }).NotTo(Panic())
   341  			})
   342  
   343  			It("fails during verification when using AtLeast(3)", func() {
   344  				Expect(func() { display.VerifyWasCalled(AtLeast(3)).Flash("Hello", 333) }).To(PanicWithMessageTo(HavePrefix(
   345  					expectation{method: "Flash(\"Hello\", 333)", expected: "at least 3", actual: "2"}.string(),
   346  				)))
   347  			})
   348  
   349  			It("succeeds during verification when using Never()", func() {
   350  				Expect(func() { display.VerifyWasCalled(Never()).Flash("Other value", 333) }).NotTo(Panic())
   351  			})
   352  
   353  			It("fails during verification when using Never()", func() {
   354  				Expect(func() { display.VerifyWasCalled(Never()).Flash("Hello", 333) }).To(PanicWithMessageTo(HavePrefix(
   355  					expectation{method: "Flash(\"Hello\", 333)", expected: "0", actual: "2"}.string(),
   356  				)))
   357  			})
   358  		})
   359  
   360  		Context("Never calling Flash", func() {
   361  			It("succeeds during verification when using Never() and argument matchers", func() {
   362  				// https://github.com/petergtz/pegomock/issues/34
   363  				Expect(func() { display.VerifyWasCalled(Never()).Flash(AnyString(), AnyInt()) }).NotTo(Panic())
   364  			})
   365  		})
   366  	})
   367  
   368  	Context("Calling MultipleParamsAndReturnValue()", func() {
   369  
   370  		It("panics when stubbed to panic", func() {
   371  			When(display.MultipleParamsAndReturnValue(AnyString(), AnyInt())).
   372  				ThenPanic("I'm panicking")
   373  			Expect(func() {
   374  				display.MultipleParamsAndReturnValue("Some string", 123)
   375  			}).To(PanicWith("I'm panicking"))
   376  		})
   377  
   378  		It("calls back when stubbed to call back", func() {
   379  			When(display.MultipleParamsAndReturnValue(AnyString(), AnyInt())).Then(
   380  				func(params []Param) ReturnValues {
   381  					return []ReturnValue{fmt.Sprintf("%v%v", params[0], params[1])}
   382  				},
   383  			)
   384  			Expect(display.MultipleParamsAndReturnValue("string and ", 123)).
   385  				To(Equal("string and 123"))
   386  		})
   387  
   388  	})
   389  
   390  	Context("Making calls in a specific order", func() {
   391  
   392  		BeforeEach(func() {
   393  			display.Flash("Hello", 111)
   394  			display.Flash("again", 222)
   395  			display.Flash("and again", 333)
   396  		})
   397  
   398  		It("succeeds during InOrder verification when order is correct", func() {
   399  			Expect(func() {
   400  				inOrderContext := new(InOrderContext)
   401  				display.VerifyWasCalledInOrder(Once(), inOrderContext).Flash("Hello", 111)
   402  				display.VerifyWasCalledInOrder(Once(), inOrderContext).Flash("again", 222)
   403  				display.VerifyWasCalledInOrder(Once(), inOrderContext).Flash("and again", 333)
   404  			}).NotTo(Panic())
   405  		})
   406  
   407  		It("succeeds during InOrder verification when order is correct, but not all invocations are verified", func() {
   408  			Expect(func() {
   409  				inOrder := new(InOrderContext)
   410  				display.VerifyWasCalledInOrder(Once(), inOrder).Flash("Hello", 111)
   411  				// not checking for the 2nd call here
   412  				display.VerifyWasCalledInOrder(Once(), inOrder).Flash("and again", 333)
   413  			}).NotTo(Panic())
   414  		})
   415  
   416  		It("fails during InOrder verification when order is not correct", func() {
   417  			Expect(func() {
   418  				inOrder := new(InOrderContext)
   419  				display.VerifyWasCalledInOrder(Once(), inOrder).Flash("again", 222)
   420  				display.VerifyWasCalledInOrder(Once(), inOrder).Flash("Hello", 111)
   421  				display.VerifyWasCalledInOrder(Once(), inOrder).Flash("and again", 333)
   422  			}).To(PanicWithMessageTo(HavePrefix(
   423  				"Expected function call Flash(\"Hello\", 111) before function call Flash(\"again\", 222)",
   424  			)))
   425  		})
   426  
   427  	})
   428  
   429  	Context("Capturing arguments", func() {
   430  		It("Returns arguments when verifying with argument capture", func() {
   431  			display.Flash("Hello", 111)
   432  
   433  			arg1, arg2 := display.VerifyWasCalledOnce().Flash(AnyString(), AnyInt()).GetCapturedArguments()
   434  
   435  			Expect(arg1).To(Equal("Hello"))
   436  			Expect(arg2).To(Equal(111))
   437  		})
   438  
   439  		It("Returns arguments of last invocation when verifying with argument capture", func() {
   440  			display.Flash("Hello", 111)
   441  			display.Flash("Again", 222)
   442  
   443  			arg1, arg2 := display.VerifyWasCalled(AtLeast(1)).Flash(AnyString(), AnyInt()).GetCapturedArguments()
   444  
   445  			Expect(arg1).To(Equal("Again"))
   446  			Expect(arg2).To(Equal(222))
   447  		})
   448  
   449  		It("Returns arguments of all invocations when verifying with \"all\" argument capture", func() {
   450  			display.Flash("Hello", 111)
   451  			display.Flash("Again", 222)
   452  
   453  			args1, args2 := display.VerifyWasCalled(AtLeast(1)).Flash(AnyString(), AnyInt()).GetAllCapturedArguments()
   454  
   455  			Expect(args1).To(ConsistOf("Hello", "Again"))
   456  			Expect(args2).To(ConsistOf(111, 222))
   457  		})
   458  
   459  		It("Returns *array* arguments of all invocations when verifying with \"all\" argument capture", func() {
   460  			display.ArrayParam([]string{"one", "two"})
   461  			display.ArrayParam([]string{"4", "5", "3"})
   462  
   463  			args := display.VerifyWasCalled(AtLeast(1)).ArrayParam(AnyStringSlice()).GetAllCapturedArguments()
   464  
   465  			Expect(flattenStringSliceOfSlices(args)).To(ConsistOf("one", "two", "3", "4", "5"))
   466  		})
   467  
   468  	})
   469  
   470  	Context("Stubbing using string slice", func() {
   471  		It("does not panic when comparing the slices in the matcher", func() {
   472  			When(func() { display.ArrayParam([]string{"one", "two"}) }).Then(func([]Param) ReturnValues {
   473  				// do nothing, because that's not our focus here.
   474  				return nil
   475  			})
   476  			display.ArrayParam([]string{"one", "two"})
   477  		})
   478  	})
   479  
   480  	Describe("Different \"Any\" matcher scenarios", func() {
   481  		It("Succeeds when int-parameter is passed as int but veryfied as float", func() {
   482  			display.FloatParam(1)
   483  			display.VerifyWasCalledOnce().FloatParam(AnyFloat32())
   484  		})
   485  
   486  		It("Panics when interface{}-parameter is passed as int, but verified as float", func() {
   487  			Expect(func() {
   488  				display.InterfaceParam(3)
   489  				display.VerifyWasCalledOnce().InterfaceParam(AnyFloat32())
   490  			}).To(PanicWithMessageTo(HavePrefix(
   491  				expectation{method: "InterfaceParam(Any(float32))", expected: "1", actual: "0"}.string(),
   492  			)))
   493  		})
   494  
   495  		It("Panics when interface{}-parameter is passed as float, but verified as int", func() {
   496  			Expect(func() {
   497  				display.InterfaceParam(3.141)
   498  				display.VerifyWasCalledOnce().InterfaceParam(AnyInt())
   499  			}).To(PanicWithMessageTo(HavePrefix(
   500  				expectation{method: "InterfaceParam(Any(int))", expected: "1", actual: "0"}.string(),
   501  			)))
   502  		})
   503  
   504  		It("Succeeds when interface{}-parameter is passed as int and verified as int", func() {
   505  			display.InterfaceParam(3)
   506  			display.VerifyWasCalledOnce().InterfaceParam(AnyInt())
   507  		})
   508  
   509  		It("Succeeds when interface{}-parameter is passed as nil and verified as int slice", func() {
   510  			display.InterfaceParam(nil)
   511  			display.VerifyWasCalledOnce().InterfaceParam(AnyIntSlice())
   512  		})
   513  
   514  		It("Panics when interface{}-parameter is passed as nil, but verified as int", func() {
   515  			Expect(func() {
   516  				display.InterfaceParam(nil)
   517  				display.VerifyWasCalledOnce().InterfaceParam(AnyInt())
   518  			}).To(PanicWithMessageTo(HavePrefix(
   519  				expectation{method: "InterfaceParam(Any(int))", expected: "1", actual: "0"}.string(),
   520  			)))
   521  		})
   522  
   523  		It("Succeeds when error-parameter is passed as nil and verified as any error", func() {
   524  			display.ErrorParam(nil)
   525  			display.VerifyWasCalledOnce().ErrorParam(AnyError())
   526  		})
   527  
   528  		It("Succeeds when error-parameter is passed as string error and verified as any error", func() {
   529  			display.ErrorParam(errors.New("Some error"))
   530  			display.VerifyWasCalledOnce().ErrorParam(AnyError())
   531  		})
   532  
   533  		It("Succeeds when http.Request-parameter is passed as null value and verified as any http.Request", func() {
   534  			display.NetHttpRequestParam(http.Request{})
   535  			display.VerifyWasCalledOnce().NetHttpRequestParam(AnyRequest())
   536  		})
   537  
   538  		It("Succeeds when http.Request-parameter is passed as null value to interface{} and verified as any http.Request", func() {
   539  			display.InterfaceParam(http.Request{})
   540  			display.VerifyWasCalledOnce().InterfaceParam(AnyRequest())
   541  		})
   542  
   543  		It("Fails when *pointer* to http.Request-parameter is passed to interface{} and verified as any http.Request", func() {
   544  			display.InterfaceParam(&http.Request{})
   545  			Expect(func() { display.VerifyWasCalledOnce().InterfaceParam(AnyRequest()) }).To(PanicWithMessageTo(SatisfyAll(
   546  				ContainSubstring("InterfaceParam(Any(http.Request))"),
   547  				ContainSubstring("InterfaceParam(&http.Request{Method"),
   548  			)))
   549  		})
   550  
   551  		It("Succeeds when http.Request-Pointer-parameter is passed as nil and verified as any *http.Request", func() {
   552  			display.NetHttpRequestPtrParam(nil)
   553  			display.VerifyWasCalledOnce().NetHttpRequestPtrParam(AnyRequestPtr())
   554  		})
   555  
   556  		It("Succeeds when http.Request-Pointer-parameter is passed as null value and verified as any *http.Request", func() {
   557  			display.NetHttpRequestPtrParam(&http.Request{})
   558  			display.VerifyWasCalledOnce().NetHttpRequestPtrParam(AnyRequestPtr())
   559  		})
   560  	})
   561  
   562  	Describe("Generated matchers", func() {
   563  		It("Succeeds when map-parameter is passed to interface{} and verified as any map", func() {
   564  			display.InterfaceParam(map[string]http.Request{"foo": http.Request{}})
   565  			display.VerifyWasCalledOnce().InterfaceParam(AnyMapOfStringToHttpRequest())
   566  		})
   567  
   568  		It("Fails when string parameter is passed to interface{} and verified as any map", func() {
   569  			display.InterfaceParam("This will not match")
   570  			Expect(func() { display.VerifyWasCalledOnce().InterfaceParam(AnyMapOfStringToHttpRequest()) }).To(PanicWithMessageTo(SatisfyAll(
   571  				ContainSubstring("InterfaceParam(Any(map[string]http.Request))"),
   572  				ContainSubstring("InterfaceParam(\"This will not match\")"),
   573  			)))
   574  		})
   575  
   576  		It("Succeeds when map-parameter is passed to interface{} and verified as eq map", func() {
   577  			display.InterfaceParam(map[string]http.Request{"foo": {}})
   578  			display.VerifyWasCalledOnce().InterfaceParam(EqMapOfStringToHttpRequest(map[string]http.Request{"foo": {}}))
   579  		})
   580  
   581  		It("Fails when map-parameter is passed to interface{} and verified as not eq map", func() {
   582  			display.InterfaceParam(map[int]int{1: 2})
   583  			Expect(func() { display.VerifyWasCalledOnce().InterfaceParam(NotEqMapOfIntToInt(map[int]int{1: 2})) }).
   584  				To(PanicWithMessageTo(ContainSubstring("InterfaceParam(NotEq(map[int]int{1:2}))")))
   585  		})
   586  
   587  		It("Succeeds when map-parameter is passed to interface{} and verified as not eq a different map", func() {
   588  			display.InterfaceParam(map[int]int{1: 2})
   589  			display.VerifyWasCalledOnce().InterfaceParam(NotEqMapOfIntToInt(map[int]int{1: 3}))
   590  		})
   591  
   592  		It("Succeeds when map-parameter is passed to interface{} and verified as not eq a time", func() {
   593  			display.InterfaceParam(map[int]int{1: 2})
   594  			display.VerifyWasCalledOnce().InterfaceParam(NotEqTimeTime(time.Now()))
   595  		})
   596  
   597  		It("Fails when map-parameter is passed to interface{} and verified as different map that satisfies equals matcher", func() {
   598  			display.InterfaceParam(map[int]int{1: 2})
   599  			Expect(func() { display.VerifyWasCalledOnce().InterfaceParam(MapOfIntToIntThat(&EqMatcher{Value: map[int]int{1: 3}})) }).
   600  				To(PanicWithMessageTo(SatisfyAll(
   601  					ContainSubstring("InterfaceParam(Eq(map[int]int{1:3}))"),
   602  					ContainSubstring("InterfaceParam(map[int]int{1:2})"),
   603  				)))
   604  		})
   605  		It("Succeeds when map-parameter is passed to interface{} and verified as map that satisfies equals matcher", func() {
   606  			display.InterfaceParam(map[int]int{1: 2})
   607  			display.VerifyWasCalledOnce().InterfaceParam(MapOfIntToIntThat(&EqMatcher{Value: map[int]int{1: 2}}))
   608  		})
   609  	})
   610  
   611  	Describe("Logic around matchers and verification", func() {
   612  		// TODO maybe this should go somewhere else
   613  		It("Fails when http.Request-parameter is passed as null value and verified as never matching http.Request", func() {
   614  			display.NetHttpRequestParam(http.Request{})
   615  			Expect(func() { display.VerifyWasCalledOnce().NetHttpRequestParam(NeverMatchingRequest()) }).
   616  				To(PanicWithMessageTo(Equal(`Mock invocation count for NetHttpRequestParam(NeverMatching) does not match expectation.
   617  
   618  	Expected: 1; but got: 0
   619  
   620  	Actual interactions with this mock were:
   621  	NetHttpRequestParam(http.Request{Method:"", URL:(*url.URL)(nil), Proto:"", ProtoMajor:0, ProtoMinor:0, Header:http.Header(nil), Body:io.ReadCloser(nil), GetBody:(func() (io.ReadCloser, error))(nil), ContentLength:0, TransferEncoding:[]string(nil), Close:false, Host:"", Form:url.Values(nil), PostForm:url.Values(nil), MultipartForm:(*multipart.Form)(nil), Trailer:http.Header(nil), RemoteAddr:"", RequestURI:"", TLS:(*tls.ConnectionState)(nil), Cancel:(<-chan struct {})(nil), Response:(*http.Response)(nil), ctx:context.Context(nil)})
   622  `)))
   623  		})
   624  	})
   625  
   626  	Describe("Stubbing with multiple ThenReturns versus multiple stubbings with same parameters", func() {
   627  		Context("One stubbing with multiple ThenReturns", func() {
   628  			It("returns the values in the order of the ThenReturns", func() {
   629  				When(display.MultipleParamsAndReturnValue("one", 1)).ThenReturn("first").ThenReturn("second")
   630  
   631  				Expect(display.MultipleParamsAndReturnValue("one", 1)).To(Equal("first"))
   632  				Expect(display.MultipleParamsAndReturnValue("one", 1)).To(Equal("second"))
   633  			})
   634  		})
   635  
   636  		Context("Multiple stubbings with same parameters", func() {
   637  			It("overrides previous stubbings with last one", func() {
   638  				When(display.MultipleParamsAndReturnValue("one", 1)).ThenReturn("first")
   639  				When(display.MultipleParamsAndReturnValue("one", 1)).ThenReturn("second")
   640  
   641  				Expect(display.MultipleParamsAndReturnValue("one", 1)).To(Equal("second"))
   642  				Expect(display.MultipleParamsAndReturnValue("one", 1)).To(Equal("second"))
   643  			})
   644  		})
   645  	})
   646  
   647  	Describe("Verifying gives hints about actual invocations in failure messages", func() {
   648  		It("shows actual interactions with same methods", func() {
   649  			display.Flash("Hello", 123)
   650  			display.Flash("Again", 456)
   651  
   652  			Expect(func() { display.VerifyWasCalledOnce().Flash("wrong string", -987) }).To(PanicWith(
   653  				"Mock invocation count for Flash(\"wrong string\", -987) " +
   654  					"does not match expectation.\n\n\tExpected: 1; but got: 0\n\n" +
   655  					"\tActual interactions with this mock were:\n" +
   656  					"\tFlash(\"Hello\", 123)\n" +
   657  					"\tFlash(\"Again\", 456)\n",
   658  			))
   659  		})
   660  
   661  		It("shows actual interactions with all methods", func() {
   662  			display.Show("Again")
   663  			display.Flash("Hello", 123)
   664  
   665  			Expect(func() { display.VerifyWasCalledOnce().Flash("wrong string", -987) }).To(PanicWith(
   666  				"Mock invocation count for Flash(\"wrong string\", -987) " +
   667  					"does not match expectation.\n\n\tExpected: 1; but got: 0\n\n" +
   668  					"\tActual interactions with this mock were:\n" +
   669  					"\tFlash(\"Hello\", 123)\n" +
   670  					"\tShow(\"Again\")\n"),
   671  			)
   672  		})
   673  
   674  		It("formats params in interactions with Go syntax for better readability", func() {
   675  			display.NetHttpRequestParam(http.Request{Host: "x.com"})
   676  			Expect(func() { display.VerifyWasCalledOnce().NetHttpRequestParam(http.Request{Host: "y.com"}) }).To(PanicWith(
   677  				`Mock invocation count for NetHttpRequestParam(http.Request{Method:"", URL:(*url.URL)(nil), Proto:"", ProtoMajor:0, ProtoMinor:0, Header:http.Header(nil), Body:io.ReadCloser(nil), GetBody:(func() (io.ReadCloser, error))(nil), ContentLength:0, TransferEncoding:[]string(nil), Close:false, Host:"y.com", Form:url.Values(nil), PostForm:url.Values(nil), MultipartForm:(*multipart.Form)(nil), Trailer:http.Header(nil), RemoteAddr:"", RequestURI:"", TLS:(*tls.ConnectionState)(nil), Cancel:(<-chan struct {})(nil), Response:(*http.Response)(nil), ctx:context.Context(nil)}) does not match expectation.
   678  
   679  	Expected: 1; but got: 0
   680  
   681  	Actual interactions with this mock were:
   682  	NetHttpRequestParam(http.Request{Method:"", URL:(*url.URL)(nil), Proto:"", ProtoMajor:0, ProtoMinor:0, Header:http.Header(nil), Body:io.ReadCloser(nil), GetBody:(func() (io.ReadCloser, error))(nil), ContentLength:0, TransferEncoding:[]string(nil), Close:false, Host:"x.com", Form:url.Values(nil), PostForm:url.Values(nil), MultipartForm:(*multipart.Form)(nil), Trailer:http.Header(nil), RemoteAddr:"", RequestURI:"", TLS:(*tls.ConnectionState)(nil), Cancel:(<-chan struct {})(nil), Response:(*http.Response)(nil), ctx:context.Context(nil)})
   683  `,
   684  			))
   685  		})
   686  
   687  		It("shows no interactions if there were none", func() {
   688  			Expect(func() { display.VerifyWasCalledOnce().Flash("wrong string", -987) }).To(PanicWith(
   689  				"Mock invocation count for Flash(\"wrong string\", -987) " +
   690  					"does not match expectation.\n\n\tExpected: 1; but got: 0\n\n" +
   691  					"\tThere were no other interactions with this mock",
   692  			))
   693  		})
   694  	})
   695  
   696  	Describe("Stubbing methods that have no return value", func() {
   697  		It("Can be stubbed with Panic", func() {
   698  			When(func() { display.Show(AnyString()) }).ThenPanic("bla")
   699  			Expect(func() { display.Show("Hello") }).To(PanicWith("bla"))
   700  		})
   701  
   702  		It("Can still work with methods returning a func", func() {
   703  			When(display.FuncReturnValue()).ThenReturn(func() { panic("It's actually a success") })
   704  			Expect(func() { display.FuncReturnValue()() }).To(PanicWith("It's actually a success"))
   705  		})
   706  
   707  		It("Panics when not using a func with no params", func() {
   708  			Expect(func() {
   709  				When(func(invalid int) { display.Show(AnyString()) })
   710  			}).To(PanicWith("When using 'When' with function that does not return a value, it expects a function with no arguments and no return value."))
   711  		})
   712  	})
   713  
   714  	Describe("Verifying methods that have variadic arguments", func() {
   715  		Context("One single variadic argument", func() {
   716  
   717  			It("succeeds when verifying one invocation with same parameters", func() {
   718  				display.VariadicParam("one", "two")
   719  				display.VerifyWasCalledOnce().VariadicParam("one", "two")
   720  			})
   721  
   722  			It("succeeds when verifying two different invocations with same parameters", func() {
   723  				display.VariadicParam("one", "two")
   724  				display.VariadicParam("three", "four", "five")
   725  				display.VerifyWasCalledOnce().VariadicParam("three", "four", "five")
   726  				display.VerifyWasCalledOnce().VariadicParam("one", "two")
   727  			})
   728  
   729  			It("succeeds when verifying one invocation with arg matchers", func() {
   730  				display.VariadicParam("one", "two")
   731  				display.VerifyWasCalledOnce().VariadicParam(AnyString(), AnyString())
   732  			})
   733  
   734  			It("succeeds when verifying two different invocations with arg matchers", func() {
   735  				display.VariadicParam("one", "two")
   736  				display.VariadicParam("three", "four", "five")
   737  				display.VerifyWasCalledOnce().VariadicParam(AnyString(), AnyString(), AnyString())
   738  				display.VerifyWasCalledOnce().VariadicParam(AnyString(), AnyString())
   739  			})
   740  
   741  			It("succeeds when verifying captured arguments", func() {
   742  				display.VariadicParam("one", "two")
   743  				args := display.VerifyWasCalledOnce().VariadicParam(AnyString(), AnyString()).GetCapturedArguments()
   744  				Expect(args[0]).To(Equal("one"))
   745  				Expect(args[1]).To(Equal("two"))
   746  			})
   747  
   748  			It("succeeds when verifying all captured arguments", func() {
   749  				display.VariadicParam("one", "two")
   750  				display.VariadicParam("three", "four", "five")
   751  				args := display.VerifyWasCalledOnce().VariadicParam(AnyString(), AnyString(), AnyString()).GetCapturedArguments()
   752  				Expect(args[0]).To(Equal("three"))
   753  				Expect(args[1]).To(Equal("four"))
   754  				Expect(args[2]).To(Equal("five"))
   755  			})
   756  
   757  		})
   758  
   759  		Context("2 normal arguments and one variadic", func() {
   760  			It("succeeds when verifying all captured arguments (one invocation match)", func() {
   761  				display.NormalAndVariadicParam("one", 2, "three", "four")
   762  				display.NormalAndVariadicParam("five", 6, "seven", "eight", "nine")
   763  
   764  				stringArg, intArg, varArgs := display.VerifyWasCalled(AtLeast(1)).NormalAndVariadicParam(AnyString(), AnyInt(), AnyString(), AnyString()).GetAllCapturedArguments()
   765  				Expect(stringArg[0]).To(Equal("one"))
   766  				Expect(intArg[0]).To(Equal(2))
   767  				Expect(varArgs[0][0]).To(Equal("three"))
   768  				Expect(varArgs[0][1]).To(Equal("four"))
   769  
   770  				stringArg, intArg, varArgs = display.VerifyWasCalled(AtLeast(1)).NormalAndVariadicParam(AnyString(), AnyInt(), AnyString(), AnyString(), AnyString()).GetAllCapturedArguments()
   771  				Expect(stringArg[0]).To(Equal("five"))
   772  				Expect(intArg[0]).To(Equal(6))
   773  				Expect(varArgs[0][0]).To(Equal("seven"))
   774  				Expect(varArgs[0][1]).To(Equal("eight"))
   775  				Expect(varArgs[0][2]).To(Equal("nine"))
   776  			})
   777  
   778  			It("succeeds when verifying all captured arguments (multiple invocation matches)", func() {
   779  				display.NormalAndVariadicParam("one", 2, "three", "four")
   780  				display.NormalAndVariadicParam("five", 6, "seven", "eight", "nine")
   781  				display.NormalAndVariadicParam("ten", 11, "twelf", "thirteen", "fourteen")
   782  
   783  				stringArg, intArg, varArgs := display.VerifyWasCalled(AtLeast(1)).NormalAndVariadicParam(AnyString(), AnyInt(), AnyString(), AnyString()).GetAllCapturedArguments()
   784  				Expect(stringArg[0]).To(Equal("one"))
   785  				Expect(intArg[0]).To(Equal(2))
   786  				Expect(varArgs[0][0]).To(Equal("three"))
   787  				Expect(varArgs[0][1]).To(Equal("four"))
   788  
   789  				stringArg, intArg, varArgs = display.VerifyWasCalled(AtLeast(1)).NormalAndVariadicParam(AnyString(), AnyInt(), AnyString(), AnyString(), AnyString()).GetAllCapturedArguments()
   790  				Expect(stringArg[0]).To(Equal("five"))
   791  				Expect(intArg[0]).To(Equal(6))
   792  				Expect(varArgs[0][0]).To(Equal("seven"))
   793  				Expect(varArgs[0][1]).To(Equal("eight"))
   794  				Expect(varArgs[0][2]).To(Equal("nine"))
   795  
   796  				Expect(stringArg[1]).To(Equal("ten"))
   797  				Expect(intArg[1]).To(Equal(11))
   798  				Expect(varArgs[1][0]).To(Equal("twelf"))
   799  				Expect(varArgs[1][1]).To(Equal("thirteen"))
   800  				Expect(varArgs[1][2]).To(Equal("fourteen"))
   801  			})
   802  
   803  			It("does not panic when variadic arg has 0 params", func() {
   804  				display.VerifyWasCalled(Never()).NormalAndVariadicParam(AnyString(), AnyInt()).GetAllCapturedArguments()
   805  
   806  				display.NormalAndVariadicParam("one", 2)
   807  				display.VerifyWasCalledOnce().NormalAndVariadicParam(AnyString(), AnyInt()).GetAllCapturedArguments()
   808  			})
   809  		})
   810  
   811  		Context("Concurrent access to mock", func() {
   812  			It("does not panic", func() {
   813  				Expect(func() {
   814  					wg := sync.WaitGroup{}
   815  					for i := 0; i < 10; i++ {
   816  						wg.Add(1)
   817  
   818  						go func() {
   819  							display.SomeValue()
   820  							wg.Done()
   821  						}()
   822  					}
   823  					wg.Wait()
   824  				}).ToNot(Panic())
   825  			})
   826  
   827  			Context("Concurrent access due to one mock calling the other", func() {
   828  				It("does not deadlock", func() {
   829  					When(display.SomeValue()).Then(func(params []Param) ReturnValues {
   830  						display.Show("Some irrelevant string")
   831  						return []ReturnValue{}
   832  					})
   833  					display.SomeValue()
   834  
   835  					display.VerifyWasCalledOnce().Show(AnyString())
   836  				})
   837  			})
   838  
   839  			Context("Concurrent access with multiple stubbing and validation", func() {
   840  				It("does not panic", func() {
   841  					pegomock.
   842  						When(display.MultipleValues()).
   843  						Then(func(params []pegomock.Param) pegomock.ReturnValues {
   844  							return pegomock.ReturnValues{"MultipleValues", 42, float32(3.14)}
   845  						})
   846  
   847  					pegomock.
   848  						When(display.MultipleParamsAndReturnValue(AnyString(), AnyInt())).
   849  						Then(func(params []pegomock.Param) pegomock.ReturnValues {
   850  							return pegomock.ReturnValues{"MultipleParamsAndReturnValue" + params[0].(string)}
   851  						})
   852  
   853  					Expect(func() {
   854  						wg := sync.WaitGroup{}
   855  
   856  						for i := 0; i < 10; i++ {
   857  							wg.Add(1)
   858  
   859  							go func() {
   860  								display.MultipleValues()
   861  								display.MultipleParamsAndReturnValue("TestString", 42)
   862  								wg.Done()
   863  							}()
   864  						}
   865  
   866  						wg.Wait()
   867  
   868  						display.VerifyWasCalled(Times(10)).MultipleValues()
   869  						display.VerifyWasCalled(Times(10)).MultipleParamsAndReturnValue(AnyString(), AnyInt())
   870  						display.VerifyWasCalled(Never()).SomeValue()
   871  					}).ToNot(Panic())
   872  				})
   873  			})
   874  		})
   875  
   876  	})
   877  
   878  	Describe("Using VerifyWasCalledEventually when object under test calls goroutine", func() {
   879  		It("correctly fails when timeout is shorter than mock invocation, and succeeds, when timeout is longer", func() {
   880  			go func() {
   881  				time.Sleep(1 * time.Second)
   882  				display.Show("hello")
   883  			}()
   884  			Expect(func() { display.VerifyWasCalledEventually(Once(), 100*time.Millisecond).Show("hello") }).
   885  				To(PanicWithMessageTo(SatisfyAll(
   886  					ContainSubstring("Mock invocation count for Show(\"hello\") does not match expectation"),
   887  					ContainSubstring("after timeout of 100ms"),
   888  					ContainSubstring("Expected: 1; but got: 0"),
   889  				)))
   890  
   891  			Expect(func() { display.VerifyWasCalledEventually(Once(), 2*time.Second).Show("hello") }).NotTo(Panic())
   892  		})
   893  
   894  	})
   895  
   896  	Describe("Manipulating out args (using pointers) in Then blocks", func() {
   897  		It("correctly manipulates the out args", func() {
   898  			type Entity struct{ i int }
   899  			var input = []Entity{}
   900  			When(func() { display.InterfaceParam(AnyInterface()) }).Then(func(params []pegomock.Param) pegomock.ReturnValues {
   901  				*params[0].(*[]Entity) = append(*params[0].(*[]Entity), Entity{3})
   902  				return nil
   903  			})
   904  
   905  			display.InterfaceParam(&input)
   906  
   907  			Expect(input).To(HaveLen(1))
   908  			Expect(input[0].i).To(Equal(3))
   909  		})
   910  	})
   911  
   912  	Context("Mock created with custom fail handler", func() {
   913  		It("calls custom fail handler instead of global one", func() {
   914  			failHandlerCalled := false
   915  			display := NewMockDisplay(WithFailHandler(func(message string, callerSkip ...int) {
   916  				failHandlerCalled = true
   917  			}))
   918  
   919  			display.VerifyWasCalledOnce().Show("This was never called")
   920  
   921  			Expect(failHandlerCalled).To(BeTrue())
   922  		})
   923  	})
   924  
   925  	Context("channels", func() {
   926  
   927  		Context("using send-/receive-only channels in return types", func() {
   928  			It("allows to return non-direction channels from callbacks", func() {
   929  				When(display.ChanReturnValues()).Then(func([]pegomock.Param) pegomock.ReturnValues {
   930  					return []ReturnValue{make(chan string), make(chan error)}
   931  				})
   932  				display.ChanReturnValues()
   933  			})
   934  
   935  			It("allows to return directed channels from callbacks", func() {
   936  				When(display.ChanReturnValues()).Then(func([]pegomock.Param) pegomock.ReturnValues {
   937  					return []ReturnValue{make(<-chan string), make(chan<- error)}
   938  				})
   939  				display.ChanReturnValues()
   940  			})
   941  
   942  			It("does not allow to return directed channels from callbacks with wrong direction", func() {
   943  				When(display.ChanReturnValues()).Then(func([]pegomock.Param) pegomock.ReturnValues {
   944  					return []ReturnValue{make(chan<- string), make(chan<- error)}
   945  				})
   946  
   947  				Expect(func() { display.ChanReturnValues() }).To(PanicWithMessageTo(MatchError(
   948  					"interface conversion: pegomock.ReturnValue is chan<- string, not <-chan string",
   949  				)))
   950  
   951  			})
   952  		})
   953  
   954  		Context("using send-/receive-only channels", func() {
   955  			It("generates the mock method with correct channel directions", func() {
   956  				var stringReadChan <-chan string
   957  				var errorWriteChan chan<- error
   958  				display.ChanParams(stringReadChan, errorWriteChan)
   959  			})
   960  		})
   961  	})
   962  })
   963  
   964  func flattenStringSliceOfSlices(sliceOfSlices [][]string) (result []string) {
   965  	for _, slice := range sliceOfSlices {
   966  		result = append(result, slice...)
   967  	}
   968  	return
   969  }
   970  
   971  type expectation struct {
   972  	method   string
   973  	expected string
   974  	actual   string
   975  }
   976  
   977  func (e expectation) string() string {
   978  	return fmt.Sprintf("Mock invocation count for %v does not match expectation.\n\n\tExpected: %v; but got: %v",
   979  		e.method, e.expected, e.actual)
   980  }