这是该结构及其方法的示例代码
type A struct {}
func (a *A) perfom(string){
...
...
..
}
然后我想从驻留在软件包外部的函数invoke()
(示例代码)中调用该方法
var s := A{}
func invoke(url string){
out := s.perfom(url)
...
...
}
我想通过模拟A的invoke
方法来编写函数perform
的测试用例。
在Java中,我们有mockito,jmock框架来存根方法调用。
有什么办法,我们可以模拟结构的方法调用而无需在源代码中引入interfaces
吗?
答案 0 :(得分:4)
要模拟方法调用,您需要对结构进行模拟。
对于您提供的代码示例,我建议创建一个Performer
接口来实现您的Perform
调用。您的真实结构和模拟结构都将实现此接口。
我还建议您将结构作为参数传递给invoke函数,而不要使用全局变量。
这里是一个例子:
type Performer interface {
perform()
}
type A struct {
}
func (a *A) perform() {
fmt.Println("real method")
}
type AMock struct {
}
func (a *AMock) perform () {
fmt.Println("mocked method")
}
func caller(p Performer) {
p.perform()
}
在测试中,将模拟注入到您的invoke
调用中。
在您的真实代码中,将真实结构注入您的invoke
调用中。
使用https://godoc.org/github.com/stretchr/testify/mock之类的库,您甚至可以真正轻松地验证使用正确的参数,正确的次数调用您的方法,并控制模拟的行为。
答案 1 :(得分:1)
在运行测试之前,将Perfom
方法分配给全局变量,然后使用模拟方法将其重新分配。
例如
51760447/a/a.go
:
package a
type A struct{}
func (a *A) Perfom(url string) (string, error) {
return "real data", nil
}
51760447/caller.go
:
package caller
import "github.com/mrdulin/golang/src/stackoverflow/51760447/a"
var s = a.A{}
var (
Perfom = s.Perfom
)
func Invoke(url string) string {
out, _ := Perfom(url)
return out
}
51760447/caller_test.go
:
package caller_test
import (
"reflect"
"testing"
caller "github.com/mrdulin/golang/src/stackoverflow/51760447"
)
func TestInvoke(t *testing.T) {
oPerfom := caller.Perfom
perfomCallCount := 0
caller.Perfom = func(url string) (string, error) {
perfomCallCount++
return "fake data", nil
}
defer func() {
caller.Perfom = oPerfom
}()
got := caller.Invoke("localhost")
want := "fake data"
if !reflect.DeepEqual(got, want) {
t.Errorf("should return fake data, got:%v, want: %v", got, want)
}
if !reflect.DeepEqual(perfomCallCount, 1) {
t.Errorf("Perfom method should be called once, got:%d", perfomCallCount)
}
}
单元测试结果:
=== RUN TestInvoke
--- PASS: TestInvoke (0.00s)
PASS
coverage: 100.0% of statements
ok github.com/mrdulin/golang/src/stackoverflow/51760447 0.033s
覆盖率报告: