如何使用struct / interface模拟依赖项以进行测试

时间:2017-11-14 14:14:04

标签: unit-testing go

我刚接触到这里......我的目标是在我的ready()中进行单元测试状态正在更新。我一直在关注https://engineering.aircto.com/writing-testable-code-in-golang/并试图弄清楚如何调整他们对我的用例所做的事情,尽我所能填补golang知识的空白。

我收到错误无法使用fakeSession(类型* FakeSession)作为类型* discordgo.Session准备参数但我不确定为什么

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 个答案:

答案 0 :(得分:1)

正如@Andrew所指出的那样discordgo.Session是一个go结构(来自您发布的文档链接type Session struct {

structs是go中的具体类型,无法替换。编译器允许的唯一参数ready是指向会话的指针。

要打破此依赖关系,您可以使用所需的方法创建项目所拥有和控制的自定义interface。这将允许您创建并使用假结构调用ready进行测试。

有时候第三方库已经有了接口,所以在创建自己的接口之前,通常需要扫描他们的godoc以查看哪些接口可用。

但是如果你必须创建自己的测试(我发现自己经常不得不这样做),它可能看起来像:

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

现在对discordgo.Session的依赖性已被破坏,您的测试代码可以使用其伪会话调用ready函数,然后对其进行断言!