2017-11-14 8 views
0

私はここに行くのが新しいです...私の目的は、準備が整った状態で状態が更新されていることをユニットテストすることです。私はhttps://engineering.aircto.com/writing-testable-code-in-golang/を見ていて、自分が行っていることを自分のユースケースに適応させる方法を見つけようとしています。私ができるところでゴラン知識のギャップを埋めています。テストの依存関係を模擬するためにstruct/interfaceを使用する方法

私は準備ができてに、引数に*型としてdiscordgo.SessionをfakeSession(タイプ* FakeSession)を使用することはできませんエラーを取得していますが、私はよく分からない私はこのエラーを取得していますなぜ

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

* discordgo.Sessionはインターフェイスではなく構造体に見えます。 – Andrew

+0

@Andrewあなたは正しいです、私はhttps://godoc.org/github.com/bwmarrin/discordgo#Sessionのリンクを含めるつもりでした。あなたは私がその影響を理解するのを助けることができますか? – Webnet

+1

@Webnet:goは静的に型指定されていますが、ある具体的な型を別の型に置き換えることはできません。 'ready'を、必要なメソッドだけを公開しているインターフェースを取る関数に置き換えることができるかもしれませんが、' ready'は何もしませんが、 'TestStatus'を呼び出します。 – JimB

答えて

0

@Andrewはdiscordgo.Sessionを指摘したように、外出先構造体(ドキュメントからは、あなたがtype Session struct {投稿リンク)され

structsは、コンクリートタイプのものです。代用することはできません。唯一の引数のコンパイラは、readyがセッションへのポインタであることを許可します。

この依存関係を解除するには、必要なメソッドを使用してプロジェクトによって所有され、制御されたカスタムを作成することができます。これにより、テスト用に偽の構造を持つreadyを作成して呼び出すことができます。

サードパーティ製のライブラリにはすでにインターフェイスがあるため、自分で作成する前に、使用するインターフェイスを確認するためにゴドックをスキャンするのが通常は価値があります。


しかし、あなたはテストのために独自に作成する必要があります(と私は自分自身が定期的にこれを行うには持っ見つける。)場合、それは次のようになります、今discordgo.Sessionへの依存性が破損している

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

あなたのテストコードは、偽のセッションでreadyの機能を呼び出してからアサーションを行うことができます!

+0

ありがとうございます。このアプローチを使用すると、エラー 'event.go:115:AddHandler()が無効なハンドラタイプで、ハンドラは決して呼び出されません。さらに掘り下げると、見つけられないハンドラインタフェースが必要になっているようです - https://github.com/bwmarrin/discordgo/blob/master/event.go#L111 – Webnet

+0

そして、そのライブラリの作者モックがほとんど不可能になるようにコード化しています。彼はAddHandlerへの空のインターフェースとして機能を受け入れますが、それを特定の具体的な関数型(https://github.com/bwmarrin/discordgo/blob/master/eventhandlers.go#L895)の非常に長いリストと照合します。彼のレポのチケットを開く価値があるかもしれないと彼はモックでテストすることを少し簡単にするように求める。 – Kaedys

+0

AHHHは 'ready'を登録するためのaddHandler呼び出しを見ませんでした:(:( – dm03514

関連する問題