Skip to content

Commit

Permalink
Merge pull request #441 from stretchr/revert-commits
Browse files Browse the repository at this point in the history
Revert PRs with
  • Loading branch information
ernesto-jimenez authored May 26, 2017
2 parents b6296e3 + f712be9 commit eb84487
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 263 deletions.
31 changes: 0 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,37 +180,6 @@ For more information on how to write mock code, check out the [API documentation

You can use the [mockery tool](http://github.com/vektra/mockery) to autogenerate the mock code against an interface as well, making using mocks much quicker.

### Plays well with [`goconvey`](/~https://github.com/smartystreets/goconvey)
`goconvey` is a BDD style testing framework for gophers. The `mock` package defines several assertion functions intended to
work with that framework

Here is an example test function testing a piece of code that operates on a mock called `Example`.
The test function can setup expectations (testify) for `Example` and assert that they indeed happened:

```go
package convey

import (
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/vektra/mockery/mocks"
m "github.com/stretchr/testify/mock"
)

func TestExampleMock(t *testing.T) {
Convey( "Given the example mock" , t, func() {
mock := new(mocks.Example)
mock.On("A").Return(nil)
Convey("When A is called", func() {
mock.A()
Convey("Assert A is called", func() {
So(mock, m.MethodWasCalled, "A")
})
})
})
}
```

[`suite`](http://godoc.org/github.com/stretchr/testify/suite "API documentation") package
-----------------------------------------------------------------------------------------

Expand Down
178 changes: 13 additions & 165 deletions mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ import (
"github.com/pmezard/go-difflib/difflib"
"github.com/stretchr/objx"
"github.com/stretchr/testify/assert"
"bytes"
)

const (
convey_test_passed_message = ""
)

// TestingT is an interface wrapper around *testing.T
Expand Down Expand Up @@ -218,7 +213,7 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
// Recording and responding to activity
// */

func (m *Mock) FindExpectedCall(method string, arguments ...interface{}) (int, *Call) {
func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
m.mutex.Lock()
defer m.mutex.Unlock()
for i, call := range m.ExpectedCalls {
Expand Down Expand Up @@ -292,11 +287,8 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
}
parts := strings.Split(functionPath, ".")
functionName := parts[len(parts)-1]
return m.MethodCalled(functionName, arguments...)
}

func (m *Mock) MethodCalled(functionName string, arguments ...interface{}) Arguments {
found, call := m.FindExpectedCall(functionName, arguments...)
found, call := m.findExpectedCall(functionName, arguments...)

if found < 0 {
// we have to fail here - because we don't know what to do
Expand Down Expand Up @@ -376,25 +368,6 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
// AssertExpectations asserts that everything specified with On and Return was
// in fact called as expected. Calls may have occurred in any order.
func (m *Mock) AssertExpectations(t TestingT) bool {
errorMsg := ExpectationsWereMet(m)
if errorMsg != convey_test_passed_message {
t.Errorf(errorMsg)
return false
} else {
return true
}
}

// ExpectationsWereMet is a goconvey style assertion see: /~https://github.com/smartystreets/goconvey/wiki/Assertions
// It asserts that everything specified with On and Return was
// in fact called as expected. Calls may have occurred in any order
func ExpectationsWereMet(iFace interface{}, args ...interface{}) string {
m, err := getMock(iFace)
if err != nil {
return err.Error()
}

b := new(bytes.Buffer)
var somethingMissing bool
var failedExpectations int

Expand All @@ -404,176 +377,55 @@ func ExpectationsWereMet(iFace interface{}, args ...interface{}) string {
if !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
somethingMissing = true
failedExpectations++
fmt.Fprintf(b, "\u274C\t%s(%s)\n", expectedCall.Method, expectedCall.Arguments.String())
t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
} else {
m.mutex.Lock()
if expectedCall.Repeatability > 0 {
somethingMissing = true
failedExpectations++
} else {
fmt.Fprintf(b, "\u2705\t%s(%s)\n", expectedCall.Method, expectedCall.Arguments.String())
t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
}
m.mutex.Unlock()
}
}

if somethingMissing {
fmt.Fprintf(b, "FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo())
return b.String()
} else {
return convey_test_passed_message
t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo())
}

return !somethingMissing
}

// AssertNumberOfCalls asserts that the method was called expectedCalls times.
func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
msg := NumberOfCalls(m, methodName, expectedCalls)
passedTest := msg == convey_test_passed_message
if !passedTest {
assert.Fail(t, msg)
}

return passedTest
}

func getMock(iFace interface{})(Mock, error) {
var mock Mock
if m, ok := iFace.(Mock); ok {
mock = m
} else {
iVal := reflect.ValueOf(iFace)
if iVal.Type().Kind() == reflect.Ptr {
return getMock(iVal.Elem().Interface())
} else if iVal.Type().Kind() == reflect.Struct && iVal.NumField() >= 1 {
v := iVal.Field(0)
if m, ok := v.Interface().(Mock); ok {
mock = m
} else {
return Mock{}, fmt.Errorf("Could not get mock from interface %v. Had type %v", iFace, reflect.TypeOf(iFace))
}
} else {
return Mock{}, fmt.Errorf("Could not get mock from interface %v. Had type %v", iFace, reflect.TypeOf(iFace))
}
}

return mock, nil
}

// NumberOfCalls is a goconvey style assertion see: /~https://github.com/smartystreets/goconvey/wiki/Assertions
// It asserts that the method was called expectedCalls times.
func NumberOfCalls(iFace interface{}, args ...interface{}) string {
m, err := getMock(iFace)
if err != nil {
return err.Error()
}

var methodName string
if stringVal, ok := args[0].(string); !ok {
typ := reflect.TypeOf(iFace)
return fmt.Sprintf("Argument 0 (methodName) should be a string. (was %s)", typ.Name())
} else {
methodName = stringVal
}

var expectedCalls int
if intVal, ok := args[1].(int); !ok {
typ := reflect.TypeOf(iFace)
return fmt.Sprintf("Argument 1 (expectedCalls) should be a int. (was %s)", typ.Name())
} else {
expectedCalls = intVal
}

var actualCalls int
for _, call := range m.calls() {
if call.Method == methodName {
actualCalls++
}
}

if actualCalls != expectedCalls {
return fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls)
} else {
return convey_test_passed_message
}
return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
}

// AssertCalled asserts that the method was called.
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
args := make([]interface{}, len(arguments) + 1)
args[0] = methodName
copy(args[1:], arguments)
message := MethodWasCalled(m, args...)
if message == convey_test_passed_message {
return true
} else {
assert.Fail(t, message)
if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) {
t.Logf("%v", m.expectedCalls())
return false
}
}

// MethodWasCalled is a goconvey style assertion see: /~https://github.com/smartystreets/goconvey/wiki/Assertions
// It asserts that the method was called.
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
func MethodWasCalled(iFace interface{}, args ...interface{}) string {
m, err := getMock(iFace)
if err != nil {
return err.Error()
}
var methodName string
if stringVal, ok := args[0].(string); !ok {
typ := reflect.TypeOf(iFace)
return fmt.Sprintf("Argument 0 (methodName) should be a string. (was %s)", typ.Name())
} else {
methodName = stringVal
}

if !m.methodWasCalled(methodName, args[1:]) {
return fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(args[1:]))
}

return convey_test_passed_message
return true
}

// AssertNotCalled asserts that the method was not called.
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
args := make([]interface{}, len(arguments) + 1)
args[0] = methodName
copy(args[1:], arguments)

message := MethodWasNotCalled(m, args...)
if message == convey_test_passed_message {
return true
} else {
assert.Fail(t, message)
if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) {
t.Logf("%v", m.expectedCalls())
return false
}
}

// MethodWasNotCalled is a goconvey style assertion see: /~https://github.com/smartystreets/goconvey/wiki/Assertions
// It asserts that the method was not called.
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
func MethodWasNotCalled(iFace interface{}, args ...interface{}) string {
m, err := getMock(iFace)
if err != nil {
return err.Error()
}
var methodName string
if stringVal, ok := args[0].(string); !ok {
typ := reflect.TypeOf(iFace)
return fmt.Sprintf("Argument 0 (methodName) should be a string. (was %s)", typ.Name())
} else {
methodName = stringVal
}

if m.methodWasCalled(methodName, args[1:]) {
return fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(args[1:]))
}

return convey_test_passed_message
return true
}

func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
Expand Down Expand Up @@ -863,11 +715,7 @@ func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
}

func diffArguments(expected Arguments, actual Arguments) string {
if diffString := diff(expected, actual); diffString != "" {
return fmt.Sprintf("Difference found in arguments:\n\n%s", diffString)
}

if len(expected) != len(actual) {
if len(expected) != len(actual) {
return fmt.Sprintf("Provided %v arguments, mocked for %v arguments", len(expected), len(actual))
}

Expand Down
Loading

0 comments on commit eb84487

Please sign in to comment.