doushi7805 2018-10-31 19:59
浏览 49
已采纳

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

Im using interface which I want to mock one method in it function1 in test and I wasn't able to figure it out how is the best to do it that for prod code it will provide 1 value and for test provide some mock value , can someone please give example ? (edited) this is the code:

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

The test is like this

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

But not sure how to mock it right ...

update

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条回答 默认 最新

  • doudao9896 2018-10-31 20:41
    关注

    First you need a type (any type) that implements the vInterface interface. Here's a simple example:

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

    This is a simple enough implementation which we can control: we can tell what its function1() function should return by simply setting that value to its value field.

    This mockedVInterface type is created solely for testing purposes, the production code does not need it. Put it in the same file where you have the test code (put it before Test_callSomething()).

    And here's the testing code:

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

    Note that in this simple case we could also use a simple non-struct type that has bool as its underlying type like this:

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

    And it works and testing code is also simpler:

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

    But this only works if the mockable interface has a single function with a single return value. In the general case a struct is needed.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c