如何在diff实现中使用函数接口

时间:2018-10-31 19:59:08

标签: go interface

我正在使用interface,我想在测试中{strong}模拟其中一种方法function1,但我无法弄清楚如何做到最好对于prod代码,它将提供1值,而对于test提供一些模拟值,有人可以举例吗? (编辑) 这是代码:

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)
            }
        })
    }
}

1 个答案:

答案 0 :(得分:1)

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

type mockedVInterface struct {
    value bool
}

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

这是一个我们可以控制的足够简单的实现:只需将其值设置为其function1()字段即可知道其value函数应该返回什么。

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,
        },
    }

但这仅在可模拟接口具有单个函数且具有单个返回值的情况下有效。通常情况下,需要一个结构。