【问题标题】:How to use function interface with diff implementation如何使用功能接口与 diff 实现
【发布时间】:2018-10-31 19:59:08
【问题描述】:

我正在使用 interface,我想在其中 mock 一种方法 function1 在测试中,但我无法弄清楚如何最好地为产品代码做到这一点它将提供 1 个值并为测试提供一些模拟值,有人可以举个例子吗? (已编辑) 这是代码:

https://play.golang.org/p/w367IOjADFV

package main

import (
    "fmt"
    "time"
)

type vInterface interface {
    function1() bool
}

type mStruct struct {
    info string
    time time.Time
}

func (s *mStruct) function1() bool {
    return true
}

func callSomething(si vInterface) bool {
    return si.function1()
}

func (s *mStruct) vl1() bool {
    s.time = time.Now()
    s.info = "vl1->info"
    return callSomething(s)
}

var currentVt1 mStruct

func main() {
    vl1 := currentVt1.vl1()

    fmt.Println(vl1)
}

测试是这样的

func Test_callSomething(t *testing.T) {
    type args struct {
        si vInterface
    }
    tests := []struct {
        name string
        args args
        want bool
    }{
        {
            name: "my tests",
            args: args{

            },
            want: false,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := callSomething(tt.args.si); got != tt.want {
                t.Errorf("callSomething() = %v, want %v", got, tt.want)
            }
        })
    }
}

但不知道如何正确模拟它......

更新

func Test_mStruct_vl1(t *testing.T) {
    type fields struct {
        info string
        time time.Time
    }
    tests := []struct {
        name   string
        fields fields
        want   bool
    }{
        {
            name: "some test",
            fields: struct {
                info string
                time time.Time
            }{info: "myinfo", time: time.Now() },

        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            s := &mStruct{
                info: tt.fields.info,
                time: tt.fields.time,
            }
            if got := s.vl1(); got != tt.want {
                t.Errorf("vl1() = %v, want %v", got, tt.want)
            }
        })
    }
}

【问题讨论】:

  • 不清楚你想做什么。你想嘲笑什么? mStruct.function1() 在您的代码中返回 true。您希望它在测试期间返回false
  • @icza - 我想用 function1 的不同实现来测试函数 callSomething,有时为真,有时为假

标签: go interface


【解决方案1】:

首先,您需要一个实现vInterface 接口的类型(任何类型)。这是一个简单的例子:

type mockedVInterface struct {
    value bool
}

func (m mockedVInterface) function1() bool {
    return m.value
}

这是一个我们可以控制的足够简单的实现:我们可以通过简单地将其值设置为value 字段来判断它的function1() 函数应该返回什么。

mockedVInterface 类型仅用于测试目的,生产代码不需要它。把它放在你有测试代码的同一个文件中(放在Test_callSomething()之前)。

这是测试代码:

func Test_callSomething(t *testing.T) {
    type args struct {
        si vInterface
    }
    tests := []struct {
        name string
        args args
        want bool
    }{
        {
            name: "testing false",
            args: args{
                si: mockedVInterface{value: false},
            },
            want: false,
        },
        {
            name: "testing true",
            args: args{
                si: mockedVInterface{value: true},
            },
            want: true,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := callSomething(tt.args.si); got != tt.want {
                t.Errorf("callSomething() = %v, want %v", got, tt.want)
            }
        })
    }
}

请注意,在这个简单的例子中,我们还可以使用一个简单的非结构类型,它的基础类型为 bool,如下所示:

type mockedVInterface bool

func (m mockedVInterface) function1() bool {
    return bool(m)
}

而且它的工作原理和测试代码也更简单:

tests := []struct {
        name string
        args args
        want bool
    }{
        {
            name: "testing false",
            args: args{
                si: mockedVInterface(false),
            },
            want: false,
        },
        {
            name: "testing true",
            args: args{
                si: mockedVInterface(true),
            },
            want: true,
        },
    }

但这仅适用于可模拟接口具有单个函数和单个返回值的情况。一般情况下需要一个结构体。

【讨论】:

  • 谢谢,对不起,mockedVInterface 是什么,我应该把它放在哪里测试?如果可以,你能提供完整的代码吗?
  • mockedVInterface 是一种专为测试目的而创建的新类型。你可以简单地把它放在你有Test_callSomething()的同一个测试文件中。
  • 好的,我把它放在测试函数中,但函数func (m mockedVInterface) function1() bool { return m.value }出现错误
  • @JhonD 你不能把它放在一个函数里面,把它放在之前这个函数。你不能在函数内部定义方法。
  • 谢谢,1+,你能解释一下为什么你使用mock接口而不是mock函数吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-18
  • 2023-03-07
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
  • 1970-01-01
  • 2020-07-24
  • 1970-01-01
相关资源
最近更新 更多