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"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
@ -133,8 +134,7 @@ func (m *Mocker) Mock(w io.Writer, names ...string) error {
|
|||||||
Name: meth.Name(),
|
Name: meth.Name(),
|
||||||
}
|
}
|
||||||
obj.Methods = append(obj.Methods, method)
|
obj.Methods = append(obj.Methods, method)
|
||||||
method.Params = m.extractArgs(sig, sig.Params(), "in%d")
|
method.Params, method.Returns = m.extractArgs(sig)
|
||||||
method.Returns = m.extractArgs(sig, sig.Results(), "out%d")
|
|
||||||
}
|
}
|
||||||
doc.Objects = append(doc.Objects, obj)
|
doc.Objects = append(doc.Objects, obj)
|
||||||
}
|
}
|
||||||
@ -182,26 +182,30 @@ func (m *Mocker) packageQualifier(pkg *types.Package) string {
|
|||||||
return pkg.Name()
|
return pkg.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mocker) extractArgs(sig *types.Signature, list *types.Tuple, nameFormat string) []*param {
|
func (m *Mocker) extractArgs(sig *types.Signature) (params, results []*param) {
|
||||||
var params []*param
|
pp := sig.Params()
|
||||||
listLen := list.Len()
|
for i := 0; i < pp.Len(); i++ {
|
||||||
for ii := 0; ii < listLen; ii++ {
|
p := m.buildParam(pp.At(i), "in"+strconv.Itoa(i+1))
|
||||||
p := list.At(ii)
|
|
||||||
name := p.Name()
|
|
||||||
if name == "" {
|
|
||||||
name = fmt.Sprintf(nameFormat, ii+1)
|
|
||||||
}
|
|
||||||
typename := types.TypeString(p.Type(), m.packageQualifier)
|
|
||||||
// check for final variadic argument
|
// check for final variadic argument
|
||||||
variadic := sig.Variadic() && ii == listLen-1 && typename[0:2] == "[]"
|
p.Variadic = sig.Variadic() && i == pp.Len()-1 && p.Type[0:2] == "[]"
|
||||||
param := ¶m{
|
params = append(params, p)
|
||||||
Name: name,
|
|
||||||
Type: typename,
|
|
||||||
Variadic: variadic,
|
|
||||||
}
|
}
|
||||||
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) {
|
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.
|
// expected.
|
||||||
// see https://github.com/matryer/moq/issues/5
|
// see https://github.com/matryer/moq/issues/5
|
||||||
func TestVariadicArguments(t *testing.T) {
|
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) {
|
func TestNothingToReturn(t *testing.T) {
|
||||||
m, err := New(Config{SrcDir: "testpackages/example"})
|
m, err := New(Config{SrcDir: "testpackages/example"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -320,7 +340,7 @@ func TestFormatter(t *testing.T) {
|
|||||||
|
|
||||||
func matchGoldenFile(goldenFile string, actual []byte) error {
|
func matchGoldenFile(goldenFile string, actual []byte) error {
|
||||||
// To update golden files, run the following:
|
// 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 *update {
|
||||||
if err := ioutil.WriteFile(goldenFile, actual, 0644); err != nil {
|
if err := ioutil.WriteFile(goldenFile, actual, 0644); err != nil {
|
||||||
return fmt.Errorf("write: %s: %s", goldenFile, err)
|
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