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.

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

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度