...

Source file src/github.com/golang/mock/gomock/controller_test.go

Documentation: github.com/golang/mock/gomock

     1  // Copyright 2011 Google Inc.
     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 gomock_test
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  	"testing"
    21  
    22  	"strings"
    23  
    24  	"github.com/golang/mock/gomock"
    25  )
    26  
    27  type ErrorReporter struct {
    28  	t          *testing.T
    29  	log        []string
    30  	failed     bool
    31  	fatalToken struct{}
    32  }
    33  
    34  func NewErrorReporter(t *testing.T) *ErrorReporter {
    35  	return &ErrorReporter{t: t}
    36  }
    37  
    38  func (e *ErrorReporter) reportLog() {
    39  	for _, entry := range e.log {
    40  		e.t.Log(entry)
    41  	}
    42  }
    43  
    44  func (e *ErrorReporter) assertPass(msg string) {
    45  	if e.failed {
    46  		e.t.Errorf("Expected pass, but got failure(s): %s", msg)
    47  		e.reportLog()
    48  	}
    49  }
    50  
    51  func (e *ErrorReporter) assertFail(msg string) {
    52  	if !e.failed {
    53  		e.t.Errorf("Expected failure, but got pass: %s", msg)
    54  	}
    55  }
    56  
    57  // Use to check that code triggers a fatal test failure.
    58  func (e *ErrorReporter) assertFatal(fn func(), expectedErrMsgs ...string) {
    59  	defer func() {
    60  		err := recover()
    61  		if err == nil {
    62  			var actual string
    63  			if e.failed {
    64  				actual = "non-fatal failure"
    65  			} else {
    66  				actual = "pass"
    67  			}
    68  			e.t.Error("Expected fatal failure, but got a", actual)
    69  		} else if token, ok := err.(*struct{}); ok && token == &e.fatalToken {
    70  			// This is okay - the panic is from Fatalf().
    71  			if expectedErrMsgs != nil {
    72  				// assert that the actual error message
    73  				// contains expectedErrMsgs
    74  
    75  				// check the last actualErrMsg, because the previous messages come from previous errors
    76  				actualErrMsg := e.log[len(e.log)-1]
    77  				for _, expectedErrMsg := range expectedErrMsgs {
    78  					if !strings.Contains(actualErrMsg, expectedErrMsg) {
    79  						e.t.Errorf("Error message:\ngot: %q\nwant to contain: %q\n", actualErrMsg, expectedErrMsg)
    80  					}
    81  				}
    82  			}
    83  			return
    84  		} else {
    85  			// Some other panic.
    86  			panic(err)
    87  		}
    88  	}()
    89  
    90  	fn()
    91  }
    92  
    93  // recoverUnexpectedFatal can be used as a deferred call in test cases to
    94  // recover from and display a call to ErrorReporter.Fatalf().
    95  func (e *ErrorReporter) recoverUnexpectedFatal() {
    96  	err := recover()
    97  	if err == nil {
    98  		// No panic.
    99  	} else if token, ok := err.(*struct{}); ok && token == &e.fatalToken {
   100  		// Unexpected fatal error happened.
   101  		e.t.Error("Got unexpected fatal error(s). All errors up to this point:")
   102  		e.reportLog()
   103  		return
   104  	} else {
   105  		// Some other panic.
   106  		panic(err)
   107  	}
   108  }
   109  
   110  func (e *ErrorReporter) Log(args ...interface{}) {
   111  	e.log = append(e.log, fmt.Sprint(args...))
   112  }
   113  
   114  func (e *ErrorReporter) Logf(format string, args ...interface{}) {
   115  	e.log = append(e.log, fmt.Sprintf(format, args...))
   116  }
   117  
   118  func (e *ErrorReporter) Errorf(format string, args ...interface{}) {
   119  	e.Logf(format, args...)
   120  	e.failed = true
   121  }
   122  
   123  func (e *ErrorReporter) Fatalf(format string, args ...interface{}) {
   124  	e.Logf(format, args...)
   125  	e.failed = true
   126  	panic(&e.fatalToken)
   127  }
   128  
   129  type HelperReporter struct {
   130  	gomock.TestReporter
   131  	helper int
   132  }
   133  
   134  func (h *HelperReporter) Helper() {
   135  	h.helper++
   136  }
   137  
   138  // A type purely for use as a receiver in testing the Controller.
   139  type Subject struct{}
   140  
   141  func (s *Subject) FooMethod(arg string) int {
   142  	return 0
   143  }
   144  
   145  func (s *Subject) BarMethod(arg string) int {
   146  	return 0
   147  }
   148  
   149  func (s *Subject) VariadicMethod(arg int, vararg ...string) {}
   150  
   151  // A type purely for ActOnTestStructMethod
   152  type TestStruct struct {
   153  	Number  int
   154  	Message string
   155  }
   156  
   157  func (s *Subject) ActOnTestStructMethod(arg TestStruct, arg1 int) int {
   158  	return 0
   159  }
   160  
   161  func (s *Subject) SetArgMethod(sliceArg []byte, ptrArg *int, mapArg map[interface{}]interface{}) {}
   162  func (s *Subject) SetArgMethodInterface(sliceArg, ptrArg, mapArg interface{})                    {}
   163  
   164  func assertEqual(t *testing.T, expected interface{}, actual interface{}) {
   165  	if !reflect.DeepEqual(expected, actual) {
   166  		t.Errorf("Expected %+v, but got %+v", expected, actual)
   167  	}
   168  }
   169  
   170  func createFixtures(t *testing.T) (reporter *ErrorReporter, ctrl *gomock.Controller) {
   171  	// reporter acts as a testing.T-like object that we pass to the
   172  	// Controller. We use it to test that the mock considered tests
   173  	// successful or failed.
   174  	reporter = NewErrorReporter(t)
   175  	ctrl = gomock.NewController(reporter)
   176  	return
   177  }
   178  
   179  func TestNoCalls(t *testing.T) {
   180  	reporter, ctrl := createFixtures(t)
   181  	ctrl.Finish()
   182  	reporter.assertPass("No calls expected or made.")
   183  }
   184  
   185  func TestNoRecordedCallsForAReceiver(t *testing.T) {
   186  	reporter, ctrl := createFixtures(t)
   187  	subject := new(Subject)
   188  
   189  	reporter.assertFatal(func() {
   190  		ctrl.Call(subject, "NotRecordedMethod", "argument")
   191  	}, "Unexpected call to", "there are no expected calls of the method \"NotRecordedMethod\" for that receiver")
   192  	ctrl.Finish()
   193  }
   194  
   195  func TestNoRecordedMatchingMethodNameForAReceiver(t *testing.T) {
   196  	reporter, ctrl := createFixtures(t)
   197  	subject := new(Subject)
   198  
   199  	ctrl.RecordCall(subject, "FooMethod", "argument")
   200  	reporter.assertFatal(func() {
   201  		ctrl.Call(subject, "NotRecordedMethod", "argument")
   202  	}, "Unexpected call to", "there are no expected calls of the method \"NotRecordedMethod\" for that receiver")
   203  	reporter.assertFatal(func() {
   204  		// The expected call wasn't made.
   205  		ctrl.Finish()
   206  	})
   207  }
   208  
   209  // This tests that a call with an arguments of some primitive type matches a recorded call.
   210  func TestExpectedMethodCall(t *testing.T) {
   211  	reporter, ctrl := createFixtures(t)
   212  	subject := new(Subject)
   213  
   214  	ctrl.RecordCall(subject, "FooMethod", "argument")
   215  	ctrl.Call(subject, "FooMethod", "argument")
   216  	ctrl.Finish()
   217  
   218  	reporter.assertPass("Expected method call made.")
   219  }
   220  
   221  func TestUnexpectedMethodCall(t *testing.T) {
   222  	reporter, ctrl := createFixtures(t)
   223  	subject := new(Subject)
   224  
   225  	reporter.assertFatal(func() {
   226  		ctrl.Call(subject, "FooMethod", "argument")
   227  	})
   228  
   229  	ctrl.Finish()
   230  }
   231  
   232  func TestRepeatedCall(t *testing.T) {
   233  	reporter, ctrl := createFixtures(t)
   234  	subject := new(Subject)
   235  
   236  	ctrl.RecordCall(subject, "FooMethod", "argument").Times(3)
   237  	ctrl.Call(subject, "FooMethod", "argument")
   238  	ctrl.Call(subject, "FooMethod", "argument")
   239  	ctrl.Call(subject, "FooMethod", "argument")
   240  	reporter.assertPass("After expected repeated method calls.")
   241  	reporter.assertFatal(func() {
   242  		ctrl.Call(subject, "FooMethod", "argument")
   243  	})
   244  	ctrl.Finish()
   245  	reporter.assertFail("After calling one too many times.")
   246  }
   247  
   248  func TestUnexpectedArgCount(t *testing.T) {
   249  	reporter, ctrl := createFixtures(t)
   250  	defer reporter.recoverUnexpectedFatal()
   251  	subject := new(Subject)
   252  
   253  	ctrl.RecordCall(subject, "FooMethod", "argument")
   254  	reporter.assertFatal(func() {
   255  		// This call is made with the wrong number of arguments...
   256  		ctrl.Call(subject, "FooMethod", "argument", "extra_argument")
   257  	}, "Unexpected call to", "wrong number of arguments", "Got: 2, want: 1")
   258  	reporter.assertFatal(func() {
   259  		// ... so is this.
   260  		ctrl.Call(subject, "FooMethod")
   261  	}, "Unexpected call to", "wrong number of arguments", "Got: 0, want: 1")
   262  	reporter.assertFatal(func() {
   263  		// The expected call wasn't made.
   264  		ctrl.Finish()
   265  	})
   266  }
   267  
   268  // This tests that a call with complex arguments (a struct and some primitive type) matches a recorded call.
   269  func TestExpectedMethodCall_CustomStruct(t *testing.T) {
   270  	reporter, ctrl := createFixtures(t)
   271  	subject := new(Subject)
   272  
   273  	expectedArg0 := TestStruct{Number: 123, Message: "hello"}
   274  	ctrl.RecordCall(subject, "ActOnTestStructMethod", expectedArg0, 15)
   275  	ctrl.Call(subject, "ActOnTestStructMethod", expectedArg0, 15)
   276  
   277  	reporter.assertPass("Expected method call made.")
   278  }
   279  
   280  func TestUnexpectedArgValue_FirstArg(t *testing.T) {
   281  	reporter, ctrl := createFixtures(t)
   282  	defer reporter.recoverUnexpectedFatal()
   283  	subject := new(Subject)
   284  
   285  	expectedArg0 := TestStruct{Number: 123, Message: "hello %s"}
   286  	ctrl.RecordCall(subject, "ActOnTestStructMethod", expectedArg0, 15)
   287  
   288  	reporter.assertFatal(func() {
   289  		// the method argument (of TestStruct type) has 1 unexpected value (for the Message field)
   290  		ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "no message"}, 15)
   291  	}, "Unexpected call to", "doesn't match the argument at index 0",
   292  		"Got: {123 no message} (gomock_test.TestStruct)\nWant: is equal to {123 hello %s} (gomock_test.TestStruct)")
   293  
   294  	reporter.assertFatal(func() {
   295  		// the method argument (of TestStruct type) has 2 unexpected values (for both fields)
   296  		ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 11, Message: "no message"}, 15)
   297  	}, "Unexpected call to", "doesn't match the argument at index 0",
   298  		"Got: {11 no message} (gomock_test.TestStruct)\nWant: is equal to {123 hello %s} (gomock_test.TestStruct)")
   299  
   300  	reporter.assertFatal(func() {
   301  		// The expected call wasn't made.
   302  		ctrl.Finish()
   303  	})
   304  }
   305  
   306  func TestUnexpectedArgValue_SecondArg(t *testing.T) {
   307  	reporter, ctrl := createFixtures(t)
   308  	defer reporter.recoverUnexpectedFatal()
   309  	subject := new(Subject)
   310  
   311  	expectedArg0 := TestStruct{Number: 123, Message: "hello"}
   312  	ctrl.RecordCall(subject, "ActOnTestStructMethod", expectedArg0, 15)
   313  
   314  	reporter.assertFatal(func() {
   315  		ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "hello"}, 3)
   316  	}, "Unexpected call to", "doesn't match the argument at index 1",
   317  		"Got: 3 (int)\nWant: is equal to 15 (int)")
   318  
   319  	reporter.assertFatal(func() {
   320  		// The expected call wasn't made.
   321  		ctrl.Finish()
   322  	})
   323  }
   324  
   325  func TestUnexpectedArgValue_WantFormatter(t *testing.T) {
   326  	reporter, ctrl := createFixtures(t)
   327  	defer reporter.recoverUnexpectedFatal()
   328  	subject := new(Subject)
   329  
   330  	expectedArg0 := TestStruct{Number: 123, Message: "hello"}
   331  	ctrl.RecordCall(
   332  		subject,
   333  		"ActOnTestStructMethod",
   334  		expectedArg0,
   335  		gomock.WantFormatter(
   336  			gomock.StringerFunc(func() string { return "is equal to fifteen" }),
   337  			gomock.Eq(15),
   338  		),
   339  	)
   340  
   341  	reporter.assertFatal(func() {
   342  		ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "hello"}, 3)
   343  	}, "Unexpected call to", "doesn't match the argument at index 1",
   344  		"Got: 3 (int)\nWant: is equal to fifteen")
   345  
   346  	reporter.assertFatal(func() {
   347  		// The expected call wasn't made.
   348  		ctrl.Finish()
   349  	})
   350  }
   351  
   352  func TestUnexpectedArgValue_GotFormatter(t *testing.T) {
   353  	reporter, ctrl := createFixtures(t)
   354  	defer reporter.recoverUnexpectedFatal()
   355  	subject := new(Subject)
   356  
   357  	expectedArg0 := TestStruct{Number: 123, Message: "hello"}
   358  	ctrl.RecordCall(
   359  		subject,
   360  		"ActOnTestStructMethod",
   361  		expectedArg0,
   362  		gomock.GotFormatterAdapter(
   363  			gomock.GotFormatterFunc(func(i interface{}) string {
   364  				// Leading 0s
   365  				return fmt.Sprintf("%02d", i)
   366  			}),
   367  			gomock.Eq(15),
   368  		),
   369  	)
   370  
   371  	reporter.assertFatal(func() {
   372  		ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "hello"}, 3)
   373  	}, "Unexpected call to", "doesn't match the argument at index 1",
   374  		"Got: 03\nWant: is equal to 15")
   375  
   376  	reporter.assertFatal(func() {
   377  		// The expected call wasn't made.
   378  		ctrl.Finish()
   379  	})
   380  }
   381  
   382  func TestAnyTimes(t *testing.T) {
   383  	reporter, ctrl := createFixtures(t)
   384  	subject := new(Subject)
   385  
   386  	ctrl.RecordCall(subject, "FooMethod", "argument").AnyTimes()
   387  	for i := 0; i < 100; i++ {
   388  		ctrl.Call(subject, "FooMethod", "argument")
   389  	}
   390  	reporter.assertPass("After 100 method calls.")
   391  	ctrl.Finish()
   392  }
   393  
   394  func TestMinTimes1(t *testing.T) {
   395  	// It fails if there are no calls
   396  	reporter, ctrl := createFixtures(t)
   397  	subject := new(Subject)
   398  	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
   399  	reporter.assertFatal(func() {
   400  		ctrl.Finish()
   401  	})
   402  
   403  	// It succeeds if there is one call
   404  	_, ctrl = createFixtures(t)
   405  	subject = new(Subject)
   406  	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
   407  	ctrl.Call(subject, "FooMethod", "argument")
   408  	ctrl.Finish()
   409  
   410  	// It succeeds if there are many calls
   411  	_, ctrl = createFixtures(t)
   412  	subject = new(Subject)
   413  	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
   414  	for i := 0; i < 100; i++ {
   415  		ctrl.Call(subject, "FooMethod", "argument")
   416  	}
   417  	ctrl.Finish()
   418  }
   419  
   420  func TestMaxTimes1(t *testing.T) {
   421  	// It succeeds if there are no calls
   422  	_, ctrl := createFixtures(t)
   423  	subject := new(Subject)
   424  	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
   425  	ctrl.Finish()
   426  
   427  	// It succeeds if there is one call
   428  	_, ctrl = createFixtures(t)
   429  	subject = new(Subject)
   430  	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
   431  	ctrl.Call(subject, "FooMethod", "argument")
   432  	ctrl.Finish()
   433  
   434  	// It fails if there are more
   435  	reporter, ctrl := createFixtures(t)
   436  	subject = new(Subject)
   437  	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
   438  	ctrl.Call(subject, "FooMethod", "argument")
   439  	reporter.assertFatal(func() {
   440  		ctrl.Call(subject, "FooMethod", "argument")
   441  	})
   442  	ctrl.Finish()
   443  }
   444  
   445  func TestMinMaxTimes(t *testing.T) {
   446  	// It fails if there are less calls than specified
   447  	reporter, ctrl := createFixtures(t)
   448  	subject := new(Subject)
   449  	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(2).MaxTimes(2)
   450  	ctrl.Call(subject, "FooMethod", "argument")
   451  	reporter.assertFatal(func() {
   452  		ctrl.Finish()
   453  	})
   454  
   455  	// It fails if there are more calls than specified
   456  	reporter, ctrl = createFixtures(t)
   457  	subject = new(Subject)
   458  	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(2).MaxTimes(2)
   459  	ctrl.Call(subject, "FooMethod", "argument")
   460  	ctrl.Call(subject, "FooMethod", "argument")
   461  	reporter.assertFatal(func() {
   462  		ctrl.Call(subject, "FooMethod", "argument")
   463  	})
   464  
   465  	// It succeeds if there is just the right number of calls
   466  	_, ctrl = createFixtures(t)
   467  	subject = new(Subject)
   468  	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(2).MinTimes(2)
   469  	ctrl.Call(subject, "FooMethod", "argument")
   470  	ctrl.Call(subject, "FooMethod", "argument")
   471  	ctrl.Finish()
   472  
   473  	// If MaxTimes is called after MinTimes is called with 1, MaxTimes takes precedence.
   474  	reporter, ctrl = createFixtures(t)
   475  	subject = new(Subject)
   476  	ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1).MaxTimes(2)
   477  	ctrl.Call(subject, "FooMethod", "argument")
   478  	ctrl.Call(subject, "FooMethod", "argument")
   479  	reporter.assertFatal(func() {
   480  		ctrl.Call(subject, "FooMethod", "argument")
   481  	})
   482  
   483  	// If MinTimes is called after MaxTimes is called with 1, MinTimes takes precedence.
   484  	_, ctrl = createFixtures(t)
   485  	subject = new(Subject)
   486  	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1).MinTimes(2)
   487  	for i := 0; i < 100; i++ {
   488  		ctrl.Call(subject, "FooMethod", "argument")
   489  	}
   490  	ctrl.Finish()
   491  }
   492  
   493  func TestDo(t *testing.T) {
   494  	_, ctrl := createFixtures(t)
   495  	subject := new(Subject)
   496  
   497  	doCalled := false
   498  	var argument string
   499  	wantArg := "argument"
   500  	ctrl.RecordCall(subject, "FooMethod", wantArg).Do(
   501  		func(arg string) {
   502  			doCalled = true
   503  			argument = arg
   504  		})
   505  	if doCalled {
   506  		t.Error("Do() callback called too early.")
   507  	}
   508  
   509  	ctrl.Call(subject, "FooMethod", wantArg)
   510  
   511  	if !doCalled {
   512  		t.Error("Do() callback not called.")
   513  	}
   514  	if wantArg != argument {
   515  		t.Error("Do callback received wrong argument.")
   516  	}
   517  
   518  	ctrl.Finish()
   519  }
   520  
   521  func TestDoAndReturn(t *testing.T) {
   522  	_, ctrl := createFixtures(t)
   523  	subject := new(Subject)
   524  
   525  	doCalled := false
   526  	var argument string
   527  	wantArg := "argument"
   528  	ctrl.RecordCall(subject, "FooMethod", wantArg).DoAndReturn(
   529  		func(arg string) int {
   530  			doCalled = true
   531  			argument = arg
   532  			return 5
   533  		})
   534  	if doCalled {
   535  		t.Error("Do() callback called too early.")
   536  	}
   537  
   538  	rets := ctrl.Call(subject, "FooMethod", wantArg)
   539  
   540  	if !doCalled {
   541  		t.Error("Do() callback not called.")
   542  	}
   543  	if wantArg != argument {
   544  		t.Error("Do callback received wrong argument.")
   545  	}
   546  	if len(rets) != 1 {
   547  		t.Fatalf("Return values from Call: got %d, want 1", len(rets))
   548  	}
   549  	if ret, ok := rets[0].(int); !ok {
   550  		t.Fatalf("Return value is not an int")
   551  	} else if ret != 5 {
   552  		t.Errorf("DoAndReturn return value: got %d, want 5", ret)
   553  	}
   554  
   555  	ctrl.Finish()
   556  }
   557  
   558  func TestSetArgSlice(t *testing.T) {
   559  	_, ctrl := createFixtures(t)
   560  	subject := new(Subject)
   561  
   562  	var in = []byte{4, 5, 6}
   563  	var set = []byte{1, 2, 3}
   564  	ctrl.RecordCall(subject, "SetArgMethod", in, nil, nil).SetArg(0, set)
   565  	ctrl.Call(subject, "SetArgMethod", in, nil, nil)
   566  
   567  	if !reflect.DeepEqual(in, set) {
   568  		t.Error("Expected SetArg() to modify input slice argument")
   569  	}
   570  
   571  	ctrl.RecordCall(subject, "SetArgMethodInterface", in, nil, nil).SetArg(0, set)
   572  	ctrl.Call(subject, "SetArgMethodInterface", in, nil, nil)
   573  
   574  	if !reflect.DeepEqual(in, set) {
   575  		t.Error("Expected SetArg() to modify input slice argument as interface{}")
   576  	}
   577  
   578  	ctrl.Finish()
   579  }
   580  
   581  func TestSetArgMap(t *testing.T) {
   582  	_, ctrl := createFixtures(t)
   583  	subject := new(Subject)
   584  
   585  	var in = map[interface{}]interface{}{"int": 1, "string": "random string", 1: "1", 0: 0}
   586  	var set = map[interface{}]interface{}{"int": 2, 1: "2", 2: 100}
   587  	ctrl.RecordCall(subject, "SetArgMethod", nil, nil, in).SetArg(2, set)
   588  	ctrl.Call(subject, "SetArgMethod", nil, nil, in)
   589  
   590  	if !reflect.DeepEqual(in, set) {
   591  		t.Error("Expected SetArg() to modify input map argument")
   592  	}
   593  
   594  	ctrl.RecordCall(subject, "SetArgMethodInterface", nil, nil, in).SetArg(2, set)
   595  	ctrl.Call(subject, "SetArgMethodInterface", nil, nil, in)
   596  
   597  	if !reflect.DeepEqual(in, set) {
   598  		t.Error("Expected SetArg() to modify input map argument as interface{}")
   599  	}
   600  
   601  	ctrl.Finish()
   602  }
   603  
   604  func TestSetArgPtr(t *testing.T) {
   605  	_, ctrl := createFixtures(t)
   606  	subject := new(Subject)
   607  
   608  	var in int = 43
   609  	const set = 42
   610  	ctrl.RecordCall(subject, "SetArgMethod", nil, &in, nil).SetArg(1, set)
   611  	ctrl.Call(subject, "SetArgMethod", nil, &in, nil)
   612  
   613  	if in != set {
   614  		t.Error("Expected SetArg() to modify value pointed to by argument")
   615  	}
   616  
   617  	ctrl.RecordCall(subject, "SetArgMethodInterface", nil, &in, nil).SetArg(1, set)
   618  	ctrl.Call(subject, "SetArgMethodInterface", nil, &in, nil)
   619  
   620  	if in != set {
   621  		t.Error("Expected SetArg() to modify value pointed to by argument as interface{}")
   622  	}
   623  	ctrl.Finish()
   624  }
   625  
   626  func TestReturn(t *testing.T) {
   627  	_, ctrl := createFixtures(t)
   628  	subject := new(Subject)
   629  
   630  	// Unspecified return should produce "zero" result.
   631  	ctrl.RecordCall(subject, "FooMethod", "zero")
   632  	ctrl.RecordCall(subject, "FooMethod", "five").Return(5)
   633  
   634  	assertEqual(
   635  		t,
   636  		[]interface{}{0},
   637  		ctrl.Call(subject, "FooMethod", "zero"))
   638  
   639  	assertEqual(
   640  		t,
   641  		[]interface{}{5},
   642  		ctrl.Call(subject, "FooMethod", "five"))
   643  	ctrl.Finish()
   644  }
   645  
   646  func TestUnorderedCalls(t *testing.T) {
   647  	reporter, ctrl := createFixtures(t)
   648  	defer reporter.recoverUnexpectedFatal()
   649  	subjectTwo := new(Subject)
   650  	subjectOne := new(Subject)
   651  
   652  	ctrl.RecordCall(subjectOne, "FooMethod", "1")
   653  	ctrl.RecordCall(subjectOne, "BarMethod", "2")
   654  	ctrl.RecordCall(subjectTwo, "FooMethod", "3")
   655  	ctrl.RecordCall(subjectTwo, "BarMethod", "4")
   656  
   657  	// Make the calls in a different order, which should be fine.
   658  	ctrl.Call(subjectOne, "BarMethod", "2")
   659  	ctrl.Call(subjectTwo, "FooMethod", "3")
   660  	ctrl.Call(subjectTwo, "BarMethod", "4")
   661  	ctrl.Call(subjectOne, "FooMethod", "1")
   662  
   663  	reporter.assertPass("After making all calls in different order")
   664  
   665  	ctrl.Finish()
   666  
   667  	reporter.assertPass("After finish")
   668  }
   669  
   670  func commonTestOrderedCalls(t *testing.T) (reporter *ErrorReporter, ctrl *gomock.Controller, subjectOne, subjectTwo *Subject) {
   671  	reporter, ctrl = createFixtures(t)
   672  
   673  	subjectOne = new(Subject)
   674  	subjectTwo = new(Subject)
   675  
   676  	gomock.InOrder(
   677  		ctrl.RecordCall(subjectOne, "FooMethod", "1").AnyTimes(),
   678  		ctrl.RecordCall(subjectTwo, "FooMethod", "2"),
   679  		ctrl.RecordCall(subjectTwo, "BarMethod", "3"),
   680  	)
   681  
   682  	return
   683  }
   684  
   685  func TestOrderedCallsCorrect(t *testing.T) {
   686  	reporter, ctrl, subjectOne, subjectTwo := commonTestOrderedCalls(t)
   687  
   688  	ctrl.Call(subjectOne, "FooMethod", "1")
   689  	ctrl.Call(subjectTwo, "FooMethod", "2")
   690  	ctrl.Call(subjectTwo, "BarMethod", "3")
   691  
   692  	ctrl.Finish()
   693  
   694  	reporter.assertPass("After finish")
   695  }
   696  
   697  func TestPanicOverridesExpectationChecks(t *testing.T) {
   698  	ctrl := gomock.NewController(t)
   699  	reporter := NewErrorReporter(t)
   700  
   701  	reporter.assertFatal(func() {
   702  		ctrl.RecordCall(new(Subject), "FooMethod", "1")
   703  		defer ctrl.Finish()
   704  		reporter.Fatalf("Intentional panic")
   705  	})
   706  }
   707  
   708  func TestSetArgWithBadType(t *testing.T) {
   709  	rep, ctrl := createFixtures(t)
   710  	defer ctrl.Finish()
   711  
   712  	s := new(Subject)
   713  	// This should catch a type error:
   714  	rep.assertFatal(func() {
   715  		ctrl.RecordCall(s, "FooMethod", "1").SetArg(0, "blah")
   716  	})
   717  	ctrl.Call(s, "FooMethod", "1")
   718  }
   719  
   720  func TestTimes0(t *testing.T) {
   721  	rep, ctrl := createFixtures(t)
   722  	defer ctrl.Finish()
   723  
   724  	s := new(Subject)
   725  	ctrl.RecordCall(s, "FooMethod", "arg").Times(0)
   726  	rep.assertFatal(func() {
   727  		ctrl.Call(s, "FooMethod", "arg")
   728  	})
   729  }
   730  
   731  func TestVariadicMatching(t *testing.T) {
   732  	rep, ctrl := createFixtures(t)
   733  	defer rep.recoverUnexpectedFatal()
   734  
   735  	s := new(Subject)
   736  	ctrl.RecordCall(s, "VariadicMethod", 0, "1", "2")
   737  	ctrl.Call(s, "VariadicMethod", 0, "1", "2")
   738  	ctrl.Finish()
   739  	rep.assertPass("variadic matching works")
   740  }
   741  
   742  func TestVariadicNoMatch(t *testing.T) {
   743  	rep, ctrl := createFixtures(t)
   744  	defer rep.recoverUnexpectedFatal()
   745  
   746  	s := new(Subject)
   747  	ctrl.RecordCall(s, "VariadicMethod", 0)
   748  	rep.assertFatal(func() {
   749  		ctrl.Call(s, "VariadicMethod", 1)
   750  	}, "expected call at", "doesn't match the argument at index 0",
   751  		"Got: 1 (int)\nWant: is equal to 0 (int)")
   752  	ctrl.Call(s, "VariadicMethod", 0)
   753  	ctrl.Finish()
   754  }
   755  
   756  func TestVariadicMatchingWithSlice(t *testing.T) {
   757  	testCases := [][]string{
   758  		{"1"},
   759  		{"1", "2"},
   760  	}
   761  	for _, tc := range testCases {
   762  		t.Run(fmt.Sprintf("%d arguments", len(tc)), func(t *testing.T) {
   763  			rep, ctrl := createFixtures(t)
   764  			defer rep.recoverUnexpectedFatal()
   765  
   766  			s := new(Subject)
   767  			ctrl.RecordCall(s, "VariadicMethod", 1, tc)
   768  			args := make([]interface{}, len(tc)+1)
   769  			args[0] = 1
   770  			for i, arg := range tc {
   771  				args[i+1] = arg
   772  			}
   773  			ctrl.Call(s, "VariadicMethod", args...)
   774  			ctrl.Finish()
   775  			rep.assertPass("slices can be used as matchers for variadic arguments")
   776  		})
   777  	}
   778  }
   779  
   780  func TestVariadicArgumentsGotFormatter(t *testing.T) {
   781  	rep, ctrl := createFixtures(t)
   782  	defer rep.recoverUnexpectedFatal()
   783  
   784  	s := new(Subject)
   785  	ctrl.RecordCall(
   786  		s,
   787  		"VariadicMethod",
   788  		gomock.GotFormatterAdapter(
   789  			gomock.GotFormatterFunc(func(i interface{}) string {
   790  				return fmt.Sprintf("test{%v}", i)
   791  			}),
   792  			gomock.Eq(0),
   793  		),
   794  	)
   795  
   796  	rep.assertFatal(func() {
   797  		ctrl.Call(s, "VariadicMethod", 1)
   798  	}, "expected call to", "doesn't match the argument at index 0",
   799  		"Got: test{1}\nWant: is equal to 0")
   800  	ctrl.Call(s, "VariadicMethod", 0)
   801  	ctrl.Finish()
   802  }
   803  
   804  func TestVariadicArgumentsGotFormatterTooManyArgsFailure(t *testing.T) {
   805  	rep, ctrl := createFixtures(t)
   806  	defer rep.recoverUnexpectedFatal()
   807  
   808  	s := new(Subject)
   809  	ctrl.RecordCall(
   810  		s,
   811  		"VariadicMethod",
   812  		0,
   813  		gomock.GotFormatterAdapter(
   814  			gomock.GotFormatterFunc(func(i interface{}) string {
   815  				return fmt.Sprintf("test{%v}", i)
   816  			}),
   817  			gomock.Eq("1"),
   818  		),
   819  	)
   820  
   821  	rep.assertFatal(func() {
   822  		ctrl.Call(s, "VariadicMethod", 0, "2", "3")
   823  	}, "expected call to", "doesn't match the argument at index 1",
   824  		"Got: test{[2 3]}\nWant: is equal to 1")
   825  	ctrl.Call(s, "VariadicMethod", 0, "1")
   826  	ctrl.Finish()
   827  }
   828  
   829  func TestNoHelper(t *testing.T) {
   830  	ctrlNoHelper := gomock.NewController(NewErrorReporter(t))
   831  
   832  	// doesn't panic
   833  	ctrlNoHelper.T.Helper()
   834  }
   835  
   836  func TestWithHelper(t *testing.T) {
   837  	withHelper := &HelperReporter{TestReporter: NewErrorReporter(t)}
   838  	ctrlWithHelper := gomock.NewController(withHelper)
   839  
   840  	ctrlWithHelper.T.Helper()
   841  
   842  	if withHelper.helper == 0 {
   843  		t.Fatal("expected Helper to be invoked")
   844  	}
   845  }
   846  
   847  func (e *ErrorReporter) Cleanup(f func()) {
   848  	e.t.Helper()
   849  	e.t.Cleanup(f)
   850  }
   851  
   852  func TestMultipleDefers(t *testing.T) {
   853  	reporter := NewErrorReporter(t)
   854  	reporter.Cleanup(func() {
   855  		reporter.assertPass("No errors for multiple calls to Finish")
   856  	})
   857  	ctrl := gomock.NewController(reporter)
   858  	ctrl.Finish()
   859  }
   860  
   861  // Equivalent to the TestNoRecordedCallsForAReceiver, but without explicitly
   862  // calling Finish.
   863  func TestDeferNotNeededFail(t *testing.T) {
   864  	reporter := NewErrorReporter(t)
   865  	subject := new(Subject)
   866  	var ctrl *gomock.Controller
   867  	reporter.Cleanup(func() {
   868  		reporter.assertFatal(func() {
   869  			ctrl.Call(subject, "NotRecordedMethod", "argument")
   870  		}, "Unexpected call to", "there are no expected calls of the method \"NotRecordedMethod\" for that receiver")
   871  	})
   872  	ctrl = gomock.NewController(reporter)
   873  }
   874  
   875  func TestDeferNotNeededPass(t *testing.T) {
   876  	reporter := NewErrorReporter(t)
   877  	subject := new(Subject)
   878  	var ctrl *gomock.Controller
   879  	reporter.Cleanup(func() {
   880  		reporter.assertPass("Expected method call made.")
   881  	})
   882  	ctrl = gomock.NewController(reporter)
   883  	ctrl.RecordCall(subject, "FooMethod", "argument")
   884  	ctrl.Call(subject, "FooMethod", "argument")
   885  }
   886  
   887  func TestOrderedCallsInCorrect(t *testing.T) {
   888  	reporter := NewErrorReporter(t)
   889  	subjectOne := new(Subject)
   890  	subjectTwo := new(Subject)
   891  	var ctrl *gomock.Controller
   892  	reporter.Cleanup(func() {
   893  		reporter.assertFatal(func() {
   894  			gomock.InOrder(
   895  				ctrl.RecordCall(subjectOne, "FooMethod", "1").AnyTimes(),
   896  				ctrl.RecordCall(subjectTwo, "FooMethod", "2"),
   897  				ctrl.RecordCall(subjectTwo, "BarMethod", "3"),
   898  			)
   899  			ctrl.Call(subjectOne, "FooMethod", "1")
   900  			// FooMethod(2) should be called before BarMethod(3)
   901  			ctrl.Call(subjectTwo, "BarMethod", "3")
   902  		}, "Unexpected call to", "Subject.BarMethod([3])", "doesn't have a prerequisite call satisfied")
   903  	})
   904  	ctrl = gomock.NewController(reporter)
   905  }
   906  
   907  // Test that calls that are prerequisites to other calls but have maxCalls >
   908  // minCalls are removed from the expected call set.
   909  func TestOrderedCallsWithPreReqMaxUnbounded(t *testing.T) {
   910  	reporter := NewErrorReporter(t)
   911  	subjectOne := new(Subject)
   912  	subjectTwo := new(Subject)
   913  	var ctrl *gomock.Controller
   914  	reporter.Cleanup(func() {
   915  		reporter.assertFatal(func() {
   916  			// Initially we should be able to call FooMethod("1") as many times as we
   917  			// want.
   918  			ctrl.Call(subjectOne, "FooMethod", "1")
   919  			ctrl.Call(subjectOne, "FooMethod", "1")
   920  
   921  			// But calling something that has it as a prerequite should remove it from
   922  			// the expected call set. This allows tests to ensure that FooMethod("1") is
   923  			// *not* called after FooMethod("2").
   924  			ctrl.Call(subjectTwo, "FooMethod", "2")
   925  
   926  			ctrl.Call(subjectOne, "FooMethod", "1")
   927  		})
   928  	})
   929  	ctrl = gomock.NewController(reporter)
   930  }
   931  
   932  func TestCallAfterLoopPanic(t *testing.T) {
   933  	reporter := NewErrorReporter(t)
   934  	subject := new(Subject)
   935  	var ctrl *gomock.Controller
   936  	reporter.Cleanup(func() {
   937  		firstCall := ctrl.RecordCall(subject, "FooMethod", "1")
   938  		secondCall := ctrl.RecordCall(subject, "FooMethod", "2")
   939  		thirdCall := ctrl.RecordCall(subject, "FooMethod", "3")
   940  
   941  		gomock.InOrder(firstCall, secondCall, thirdCall)
   942  
   943  		defer func() {
   944  			err := recover()
   945  			if err == nil {
   946  				t.Error("Call.After creation of dependency loop did not panic.")
   947  			}
   948  		}()
   949  
   950  		// This should panic due to dependency loop.
   951  		firstCall.After(thirdCall)
   952  	})
   953  	ctrl = gomock.NewController(reporter)
   954  }
   955  

View as plain text