How to use isCleanuper method of gomock Package

Best Mock code snippet using gomock.isCleanuper

Run Mock automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

controller.go

Source: controller.go Github

copy
1// Copyright 2010 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 is a mock framework for Go.
16//
17// Standard usage:
18//   (1) Define an interface that you wish to mock.
19//         type MyInterface interface {
20//           SomeMethod(x int64, y string)
21//         }
22//   (2) Use mockgen to generate a mock from the interface.
23//   (3) Use the mock in a test:
24//         func TestMyThing(t *testing.T) {
25//           mockCtrl := gomock.NewController(t)
26//           defer mockCtrl.Finish()
27//
28//           mockObj := something.NewMockMyInterface(mockCtrl)
29//           mockObj.EXPECT().SomeMethod(4, "blah")
30//           // pass mockObj to a real object and play with it.
31//         }
32//
33// By default, expected calls are not enforced to run in any particular order.
34// Call order dependency can be enforced by use of InOrder and/or Call.After.
35// Call.After can create more varied call order dependencies, but InOrder is
36// often more convenient.
37//
38// The following examples create equivalent call order dependencies.
39//
40// Example of using Call.After to chain expected call order:
41//
42//     firstCall := mockObj.EXPECT().SomeMethod(1, "first")
43//     secondCall := mockObj.EXPECT().SomeMethod(2, "second").After(firstCall)
44//     mockObj.EXPECT().SomeMethod(3, "third").After(secondCall)
45//
46// Example of using InOrder to declare expected call order:
47//
48//     gomock.InOrder(
49//         mockObj.EXPECT().SomeMethod(1, "first"),
50//         mockObj.EXPECT().SomeMethod(2, "second"),
51//         mockObj.EXPECT().SomeMethod(3, "third"),
52//     )
53package gomock
54
55import (
56	"context"
57	"fmt"
58	"reflect"
59	"runtime"
60	"sync"
61)
62
63// A TestReporter is something that can be used to report test failures.  It
64// is satisfied by the standard library's *testing.T.
65type TestReporter interface {
66	Errorf(format string, args ...interface{})
67	Fatalf(format string, args ...interface{})
68}
69
70// TestHelper is a TestReporter that has the Helper method.  It is satisfied
71// by the standard library's *testing.T.
72type TestHelper interface {
73	TestReporter
74	Helper()
75}
76
77// cleanuper is used to check if TestHelper also has the `Cleanup` method. A
78// common pattern is to pass in a `*testing.T` to
79// `NewController(t TestReporter)`. In Go 1.14+, `*testing.T` has a cleanup
80// method. This can be utilized to call `Finish()` so the caller of this library
81// does not have to.
82type cleanuper interface {
83	Cleanup(func())
84}
85
86// A Controller represents the top-level control of a mock ecosystem.  It
87// defines the scope and lifetime of mock objects, as well as their
88// expectations.  It is safe to call Controller's methods from multiple
89// goroutines. Each test should create a new Controller and invoke Finish via
90// defer.
91//
92//   func TestFoo(t *testing.T) {
93//     ctrl := gomock.NewController(t)
94//     defer ctrl.Finish()
95//     // ..
96//   }
97//
98//   func TestBar(t *testing.T) {
99//     t.Run("Sub-Test-1", st) {
100//       ctrl := gomock.NewController(st)
101//       defer ctrl.Finish()
102//       // ..
103//     })
104//     t.Run("Sub-Test-2", st) {
105//       ctrl := gomock.NewController(st)
106//       defer ctrl.Finish()
107//       // ..
108//     })
109//   })
110type Controller struct {
111	// T should only be called within a generated mock. It is not intended to
112	// be used in user code and may be changed in future versions. T is the
113	// TestReporter passed in when creating the Controller via NewController.
114	// If the TestReporter does not implement a TestHelper it will be wrapped
115	// with a nopTestHelper.
116	T             TestHelper
117	mu            sync.Mutex
118	expectedCalls *callSet
119	finished      bool
120}
121
122// NewController returns a new Controller. It is the preferred way to create a
123// Controller.
124//
125// New in go1.14+, if you are passing a *testing.T into this function you no
126// longer need to call ctrl.Finish() in your test methods.
127func NewController(t TestReporter) *Controller {
128	h, ok := t.(TestHelper)
129	if !ok {
130		h = &nopTestHelper{t}
131	}
132	ctrl := &Controller{
133		T:             h,
134		expectedCalls: newCallSet(),
135	}
136	if c, ok := isCleanuper(ctrl.T); ok {
137		c.Cleanup(func() {
138			ctrl.T.Helper()
139			ctrl.finish(true, nil)
140		})
141	}
142
143	return ctrl
144}
145
146type cancelReporter struct {
147	t      TestHelper
148	cancel func()
149}
150
151func (r *cancelReporter) Errorf(format string, args ...interface{}) {
152	r.t.Errorf(format, args...)
153}
154func (r *cancelReporter) Fatalf(format string, args ...interface{}) {
155	defer r.cancel()
156	r.t.Fatalf(format, args...)
157}
158
159func (r *cancelReporter) Helper() {
160	r.t.Helper()
161}
162
163// WithContext returns a new Controller and a Context, which is cancelled on any
164// fatal failure.
165func WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context) {
166	h, ok := t.(TestHelper)
167	if !ok {
168		h = &nopTestHelper{t: t}
169	}
170
171	ctx, cancel := context.WithCancel(ctx)
172	return NewController(&cancelReporter{t: h, cancel: cancel}), ctx
173}
174
175type nopTestHelper struct {
176	t TestReporter
177}
178
179func (h *nopTestHelper) Errorf(format string, args ...interface{}) {
180	h.t.Errorf(format, args...)
181}
182func (h *nopTestHelper) Fatalf(format string, args ...interface{}) {
183	h.t.Fatalf(format, args...)
184}
185
186func (h nopTestHelper) Helper() {}
187
188// RecordCall is called by a mock. It should not be called by user code.
189func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
190	ctrl.T.Helper()
191
192	recv := reflect.ValueOf(receiver)
193	for i := 0; i < recv.Type().NumMethod(); i++ {
194		if recv.Type().Method(i).Name == method {
195			return ctrl.RecordCallWithMethodType(receiver, method, recv.Method(i).Type(), args...)
196		}
197	}
198	ctrl.T.Fatalf("gomock: failed finding method %s on %T", method, receiver)
199	panic("unreachable")
200}
201
202// RecordCallWithMethodType is called by a mock. It should not be called by user code.
203func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
204	ctrl.T.Helper()
205
206	call := newCall(ctrl.T, receiver, method, methodType, args...)
207
208	ctrl.mu.Lock()
209	defer ctrl.mu.Unlock()
210	ctrl.expectedCalls.Add(call)
211
212	return call
213}
214
215// Call is called by a mock. It should not be called by user code.
216func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} {
217	ctrl.T.Helper()
218
219	// Nest this code so we can use defer to make sure the lock is released.
220	actions := func() []func([]interface{}) []interface{} {
221		ctrl.T.Helper()
222		ctrl.mu.Lock()
223		defer ctrl.mu.Unlock()
224
225		expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args)
226		if err != nil {
227			// callerInfo's skip should be updated if the number of calls between the user's test
228			// and this line changes, i.e. this code is wrapped in another anonymous function.
229			// 0 is us, 1 is controller.Call(), 2 is the generated mock, and 3 is the user's test.
230			origin := callerInfo(3)
231			ctrl.T.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err)
232		}
233
234		// Two things happen here:
235		// * the matching call no longer needs to check prerequite calls,
236		// * and the prerequite calls are no longer expected, so remove them.
237		preReqCalls := expected.dropPrereqs()
238		for _, preReqCall := range preReqCalls {
239			ctrl.expectedCalls.Remove(preReqCall)
240		}
241
242		actions := expected.call()
243		if expected.exhausted() {
244			ctrl.expectedCalls.Remove(expected)
245		}
246		return actions
247	}()
248
249	var rets []interface{}
250	for _, action := range actions {
251		if r := action(args); r != nil {
252			rets = r
253		}
254	}
255
256	return rets
257}
258
259// Finish checks to see if all the methods that were expected to be called
260// were called. It should be invoked for each Controller. It is not idempotent
261// and therefore can only be invoked once.
262//
263// New in go1.14+, if you are passing a *testing.T into NewController function you no
264// longer need to call ctrl.Finish() in your test methods.
265func (ctrl *Controller) Finish() {
266	// If we're currently panicking, probably because this is a deferred call.
267	// This must be recovered in the deferred function.
268	err := recover()
269	ctrl.finish(false, err)
270}
271
272func (ctrl *Controller) finish(cleanup bool, panicErr interface{}) {
273	ctrl.T.Helper()
274
275	ctrl.mu.Lock()
276	defer ctrl.mu.Unlock()
277
278	if ctrl.finished {
279		if _, ok := isCleanuper(ctrl.T); !ok {
280			ctrl.T.Fatalf("Controller.Finish was called more than once. It has to be called exactly once.")
281		}
282		return
283	}
284	ctrl.finished = true
285
286	// Short-circuit, pass through the panic.
287	if panicErr != nil {
288		panic(panicErr)
289	}
290
291	// Check that all remaining expected calls are satisfied.
292	failures := ctrl.expectedCalls.Failures()
293	for _, call := range failures {
294		ctrl.T.Errorf("missing call(s) to %v", call)
295	}
296	if len(failures) != 0 {
297		if !cleanup {
298			ctrl.T.Fatalf("aborting test due to missing call(s)")
299			return
300		}
301		ctrl.T.Errorf("aborting test due to missing call(s)")
302	}
303}
304
305// callerInfo returns the file:line of the call site. skip is the number
306// of stack frames to skip when reporting. 0 is callerInfo's call site.
307func callerInfo(skip int) string {
308	if _, file, line, ok := runtime.Caller(skip + 1); ok {
309		return fmt.Sprintf("%s:%d", file, line)
310	}
311	return "unknown file"
312}
313
314// isCleanuper checks it if t's base TestReporter has a Cleanup method.
315func isCleanuper(t TestReporter) (cleanuper, bool) {
316	tr := unwrapTestReporter(t)
317	c, ok := tr.(cleanuper)
318	return c, ok
319}
320
321// unwrapTestReporter unwraps TestReporter to the base implementation.
322func unwrapTestReporter(t TestReporter) TestReporter {
323	tr := t
324	switch nt := t.(type) {
325	case *cancelReporter:
326		tr = nt.t
327		if h, check := tr.(*nopTestHelper); check {
328			tr = h.t
329		}
330	case *nopTestHelper:
331		tr = nt.t
332	default:
333		// not wrapped
334	}
335	return tr
336}
337
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)