mirror of https://github.com/stretchr/testify.git
Add T object and Test method to Mock
This makes is possible to fail the test instead of panicing in case that the method was called with unexpected arguments. Fixes #489 mock: change field 'T' to be private field 'test' mock_test: MockTestingT not using Mock anymorepull/581/head
parent
20dae58180
commit
33951ec724
31
mock/mock.go
31
mock/mock.go
|
@ -191,6 +191,10 @@ type Mock struct {
|
|||
// Holds the calls that were made to this mocked object.
|
||||
Calls []Call
|
||||
|
||||
// test is An optional variable that holds the test struct, to be used when an
|
||||
// invalid mock call was made.
|
||||
test TestingT
|
||||
|
||||
// TestData holds any data that might be useful for testing. Testify ignores
|
||||
// this data completely allowing you to do whatever you like with it.
|
||||
testData objx.Map
|
||||
|
@ -213,6 +217,27 @@ func (m *Mock) TestData() objx.Map {
|
|||
Setting expectations
|
||||
*/
|
||||
|
||||
// Test sets the test struct variable of the mock object
|
||||
func (m *Mock) Test(t TestingT) {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
m.test = t
|
||||
}
|
||||
|
||||
// fail fails the current test with the given formatted format and args.
|
||||
// In case that a test was defined, it uses the test APIs for failing a test,
|
||||
// otherwise it uses panic.
|
||||
func (m *Mock) fail(format string, args ...interface{}) {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
if m.test == nil {
|
||||
panic(fmt.Sprintf(format, args...))
|
||||
}
|
||||
m.test.Errorf(format, args...)
|
||||
m.test.FailNow()
|
||||
}
|
||||
|
||||
// On starts a description of an expectation of the specified method
|
||||
// being called.
|
||||
//
|
||||
|
@ -329,14 +354,14 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
|
|||
m.mutex.Unlock()
|
||||
|
||||
if closestCall != nil {
|
||||
panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s",
|
||||
m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s",
|
||||
callString(methodName, arguments, true),
|
||||
callString(methodName, closestCall.Arguments, true),
|
||||
diffArguments(closestCall.Arguments, arguments),
|
||||
strings.TrimSpace(mismatch)),
|
||||
strings.TrimSpace(mismatch),
|
||||
)
|
||||
} else {
|
||||
panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo()))
|
||||
m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"runtime"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -93,6 +92,34 @@ func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType)
|
|||
return args.Error(0)
|
||||
}
|
||||
|
||||
// MockTestingT mocks a test struct
|
||||
type MockTestingT struct {
|
||||
logfCount, errorfCount, failNowCount int
|
||||
}
|
||||
|
||||
const mockTestingTFailNowCalled = "FailNow was called"
|
||||
|
||||
func (m *MockTestingT) Logf(string, ...interface{}) {
|
||||
m.logfCount++
|
||||
}
|
||||
|
||||
func (m *MockTestingT) Errorf(string, ...interface{}) {
|
||||
m.errorfCount++
|
||||
}
|
||||
|
||||
// FailNow mocks the FailNow call.
|
||||
// It panics in order to mimic the FailNow behavior in the sense that
|
||||
// the execution stops.
|
||||
// When expecting this method, the call that invokes it should use the following code:
|
||||
//
|
||||
// assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() {...})
|
||||
func (m *MockTestingT) FailNow() {
|
||||
m.failNowCount++
|
||||
|
||||
// this function should panic now to stop the execution as expected
|
||||
panic(mockTestingTFailNowCalled)
|
||||
}
|
||||
|
||||
/*
|
||||
Mock
|
||||
*/
|
||||
|
@ -205,6 +232,34 @@ func Test_Mock_On_WithIntArgMatcher(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestMock_WithTest(t *testing.T) {
|
||||
var (
|
||||
mockedService TestExampleImplementation
|
||||
mockedTest MockTestingT
|
||||
)
|
||||
|
||||
mockedService.Test(&mockedTest)
|
||||
mockedService.On("TheExampleMethod", 1, 2, 3).Return(0, nil)
|
||||
|
||||
// Test that on an expected call, the test was not failed
|
||||
|
||||
mockedService.TheExampleMethod(1, 2, 3)
|
||||
|
||||
// Assert that Errorf and FailNow were not called
|
||||
assert.Equal(t, 0, mockedTest.errorfCount)
|
||||
assert.Equal(t, 0, mockedTest.failNowCount)
|
||||
|
||||
// Test that on unexpected call, the mocked test was called to fail the test
|
||||
|
||||
assert.PanicsWithValue(t, mockTestingTFailNowCalled, func() {
|
||||
mockedService.TheExampleMethod(1, 1, 1)
|
||||
})
|
||||
|
||||
// Assert that Errorf and FailNow were called once
|
||||
assert.Equal(t, 1, mockedTest.errorfCount)
|
||||
assert.Equal(t, 1, mockedTest.failNowCount)
|
||||
}
|
||||
|
||||
func Test_Mock_On_WithPtrArgMatcher(t *testing.T) {
|
||||
var mockedService TestExampleImplementation
|
||||
|
||||
|
|
Loading…
Reference in New Issue