doutuan6158 2017-11-14 14:14
浏览 43
已采纳

如何使用结构/接口模拟依赖关系进行测试

I'm new to go here... my objective is to unit test that a status is being updated in my ready(). I've been looking at https://engineering.aircto.com/writing-testable-code-in-golang/ and trying to figure out how to adapt what they're doing to my use case, filling in gaps of golang knowledge where I can.

I'm getting the error cannot use fakeSession (type *FakeSession) as type *discordgo.Session in argument to ready but I'm not sure why I'm getting this error.

main.go

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"

    "github.com/bwmarrin/discordgo"
)

var (
    // bot token used for this bot when connecting
    token    = os.Getenv("DISCORD_BOT_TOKEN")
    status   = os.Getenv("BOT_STATUS")
)

func main() {
    // initiate Discord bot

    // Register ready as a callback for the ready events.
    discordConnection.AddHandler(ready)

    // running the app, waiting to receive a close signal
}

// This function will be called (due to AddHandler above) when the bot receives
// the "ready" event from Discord.
func ready(session *discordgo.Session, event *discordgo.Ready) {

    // Set the playing status.
    session.UpdateStatus(0, status)
}

main_test.go

type FakeSession struct {
    status  string
    idle    int
}

func (f *FakeSession) UpdateStatus(idle int, game string) error {
    f.idle, f.status = idle, game
    return nil
}

func TestStatusIsUpdated(t *testing.T) {
    readyDependency := &discordgo.Ready{}
    fakeSession := &FakeSession{}

    ready(fakeSession, readyDependency)

    // @todo assert that idle/game status were set to correct values
}
  • 写回答

1条回答 默认 最新

  • dongxian7489 2017-11-14 14:35
    关注

    As @Andrew pointed out discordgo.Session is a go struct (from the docs link you posted type Session struct {)

    structs are Concrete types in go and are unable to be substituted. The only argument go compiler will allow for ready is a pointer to a session.

    To break this dependency you can create a custom interface owned and controlled by your project using the methods that you need. This will allow you to create and call ready with a fake structure for your tests.

    Sometimes 3rd party libraries already have interfaces so it's usually worth-while to scan their godoc to see which interfaces are available before creating your own.


    But if you have to create your own for testing (and I find myself regularly having to do this), it might look like:

    type StatusUpdater interface {
       UpdateStatus(int, string)
    }
    
    // This function will be called (due to AddHandler above) when the bot receives
    // the "ready" event from Discord.
    func ready(s StatusUpdater, event *discordgo.Ready) {
    
        // Set the playing status.
        s.UpdateStatus(0, status)
    }
    

    Now the dependency on discordgo.Session has been broken, and your test code can call ready function with its fake session, and then make assertions on it!

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

报告相同问题?

悬赏问题

  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动