No variadic return types (#126)
While extracting the method and parameters from the method signature, only check and apply the variadic flag for the input parameters and not for the return arguments. Issue details: For an interface with variadic arguments and slice return type, moq was generating an invalid mock: type I interface { Func(params ...interface{}) []byte } // ... type IMock struct { // FuncFunc mocks the Func method. FuncFunc func(params ...interface{}) ...byte // calls tracks calls to the methods. calls struct { // Func holds details about calls to the Func method. Func []struct { // Params is the params argument value. Params []interface{} } } } On attempting to generate the mock in such an instance, the command would fail on the formatting step: m.Mock: go/format: 35:30: expected ';', found '...' (and 3 more errors) See https://github.com/matryer/moq/issues/124, https://github.com/matryer/moq/pull/125.
This commit is contained in:
parent
7721994d1b
commit
4638a53893
@ -10,6 +10,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
@ -133,8 +134,7 @@ func (m *Mocker) Mock(w io.Writer, names ...string) error {
|
||||
Name: meth.Name(),
|
||||
}
|
||||
obj.Methods = append(obj.Methods, method)
|
||||
method.Params = m.extractArgs(sig, sig.Params(), "in%d")
|
||||
method.Returns = m.extractArgs(sig, sig.Results(), "out%d")
|
||||
method.Params, method.Returns = m.extractArgs(sig)
|
||||
}
|
||||
doc.Objects = append(doc.Objects, obj)
|
||||
}
|
||||
@ -182,26 +182,30 @@ func (m *Mocker) packageQualifier(pkg *types.Package) string {
|
||||
return pkg.Name()
|
||||
}
|
||||
|
||||
func (m *Mocker) extractArgs(sig *types.Signature, list *types.Tuple, nameFormat string) []*param {
|
||||
var params []*param
|
||||
listLen := list.Len()
|
||||
for ii := 0; ii < listLen; ii++ {
|
||||
p := list.At(ii)
|
||||
name := p.Name()
|
||||
if name == "" {
|
||||
name = fmt.Sprintf(nameFormat, ii+1)
|
||||
}
|
||||
typename := types.TypeString(p.Type(), m.packageQualifier)
|
||||
func (m *Mocker) extractArgs(sig *types.Signature) (params, results []*param) {
|
||||
pp := sig.Params()
|
||||
for i := 0; i < pp.Len(); i++ {
|
||||
p := m.buildParam(pp.At(i), "in"+strconv.Itoa(i+1))
|
||||
// check for final variadic argument
|
||||
variadic := sig.Variadic() && ii == listLen-1 && typename[0:2] == "[]"
|
||||
param := ¶m{
|
||||
Name: name,
|
||||
Type: typename,
|
||||
Variadic: variadic,
|
||||
p.Variadic = sig.Variadic() && i == pp.Len()-1 && p.Type[0:2] == "[]"
|
||||
params = append(params, p)
|
||||
}
|
||||
params = append(params, param)
|
||||
|
||||
rr := sig.Results()
|
||||
for i := 0; i < rr.Len(); i++ {
|
||||
results = append(results, m.buildParam(rr.At(i), "out"+strconv.Itoa(i+1)))
|
||||
}
|
||||
return params
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (m *Mocker) buildParam(v *types.Var, fallbackName string) *param {
|
||||
name := v.Name()
|
||||
if name == "" {
|
||||
name = fallbackName
|
||||
}
|
||||
typ := types.TypeString(v.Type(), m.packageQualifier)
|
||||
return ¶m{Name: name, Type: typ}
|
||||
}
|
||||
|
||||
func pkgInfoFromPath(srcDir string, mode packages.LoadMode) (*packages.Package, error) {
|
||||
|
@ -191,7 +191,7 @@ func TestNotCreatingEmptyDirWhenPkgIsGiven(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestVeradicArguments tests to ensure variadic work as
|
||||
// TestVariadicArguments tests to ensure variadic work as
|
||||
// expected.
|
||||
// see https://github.com/matryer/moq/issues/5
|
||||
func TestVariadicArguments(t *testing.T) {
|
||||
@ -219,6 +219,26 @@ func TestVariadicArguments(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestSliceResult tests to ensure slice return data type works as
|
||||
// expected.
|
||||
// see https://github.com/matryer/moq/issues/124
|
||||
func TestSliceResult(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/variadic"})
|
||||
if err != nil {
|
||||
t.Fatalf("moq.New: %s", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err = m.Mock(&buf, "Echoer"); err != nil {
|
||||
t.Errorf("m.Mock: %s", err)
|
||||
}
|
||||
|
||||
golden := filepath.Join("testpackages/variadic/testdata", "echoer.golden.go")
|
||||
if err := matchGoldenFile(golden, buf.Bytes()); err != nil {
|
||||
t.Errorf("check golden file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNothingToReturn(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/example"})
|
||||
if err != nil {
|
||||
@ -320,7 +340,7 @@ func TestFormatter(t *testing.T) {
|
||||
|
||||
func matchGoldenFile(goldenFile string, actual []byte) error {
|
||||
// To update golden files, run the following:
|
||||
// go test -v -run ^<Test-Name>$ github.com/matryer/moq/pkg/moq -update
|
||||
// go test -v -run '^<Test-Name>$' github.com/matryer/moq/pkg/moq -update
|
||||
if *update {
|
||||
if err := ioutil.WriteFile(goldenFile, actual, 0644); err != nil {
|
||||
return fmt.Errorf("write: %s: %s", goldenFile, err)
|
||||
|
5
pkg/moq/testpackages/variadic/echoer.go
Normal file
5
pkg/moq/testpackages/variadic/echoer.go
Normal file
@ -0,0 +1,5 @@
|
||||
package variadic
|
||||
|
||||
type Echoer interface {
|
||||
Echo(ss ...string) []string
|
||||
}
|
76
pkg/moq/testpackages/variadic/testdata/echoer.golden.go
vendored
Normal file
76
pkg/moq/testpackages/variadic/testdata/echoer.golden.go
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package variadic
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
lockEchoerMockEcho sync.RWMutex
|
||||
)
|
||||
|
||||
// Ensure, that EchoerMock does implement Echoer.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ Echoer = &EchoerMock{}
|
||||
|
||||
// EchoerMock is a mock implementation of Echoer.
|
||||
//
|
||||
// func TestSomethingThatUsesEchoer(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked Echoer
|
||||
// mockedEchoer := &EchoerMock{
|
||||
// EchoFunc: func(ss ...string) []string {
|
||||
// panic("mock out the Echo method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedEchoer in code that requires Echoer
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type EchoerMock struct {
|
||||
// EchoFunc mocks the Echo method.
|
||||
EchoFunc func(ss ...string) []string
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Echo holds details about calls to the Echo method.
|
||||
Echo []struct {
|
||||
// Ss is the ss argument value.
|
||||
Ss []string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Echo calls EchoFunc.
|
||||
func (mock *EchoerMock) Echo(ss ...string) []string {
|
||||
if mock.EchoFunc == nil {
|
||||
panic("EchoerMock.EchoFunc: method is nil but Echoer.Echo was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
Ss []string
|
||||
}{
|
||||
Ss: ss,
|
||||
}
|
||||
lockEchoerMockEcho.Lock()
|
||||
mock.calls.Echo = append(mock.calls.Echo, callInfo)
|
||||
lockEchoerMockEcho.Unlock()
|
||||
return mock.EchoFunc(ss...)
|
||||
}
|
||||
|
||||
// EchoCalls gets all the calls that were made to Echo.
|
||||
// Check the length with:
|
||||
// len(mockedEchoer.EchoCalls())
|
||||
func (mock *EchoerMock) EchoCalls() []struct {
|
||||
Ss []string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ss []string
|
||||
}
|
||||
lockEchoerMockEcho.RLock()
|
||||
calls = mock.calls.Echo
|
||||
lockEchoerMockEcho.RUnlock()
|
||||
return calls
|
||||
}
|
Loading…
Reference in New Issue
Block a user