175

依存関係に困惑しています。一部の関数呼び出しをモック呼び出しに置き換えられるようにしたいと考えています。これが私のコードのスニペットです:

func get_page(url string) string {
    get_dl_slot(url)
    defer free_dl_slot(url)
    
    resp, err := http.Get(url)
    if err != nil { return "" }
    defer resp.Body.Close()
    
    contents, err := ioutil.ReadAll(resp.Body)
    if err != nil { return "" }
    return string(contents)
}

func downloader() {
    dl_slots = make(chan bool, DL_SLOT_AMOUNT) // Init the download slot semaphore
    content := get_page(BASE_URL)
    links_regexp := regexp.MustCompile(LIST_LINK_REGEXP)
    matches := links_regexp.FindAllStringSubmatch(content, -1)
    for _, match := range matches{
        go serie_dl(match[1], match[2])
    }
}

downloader()実際に http を介してページを取得せずにテストできるようにしたいと考えてget_pageいますhttp.Get()

同様の問題に関すると思われるこのスレッドを見つけました。Julian Phillips は彼のライブラリであるWithmockを解決策として提示していますが、私はそれを機能させることができません。正直なところ、これは私のテストコードの関連部分です。これは、私にとって大部分がカーゴカルトコードです。

import (
    "testing"
    "net/http" // mock
    "code.google.com/p/gomock"
)
...
func TestDownloader (t *testing.T) {
    ctrl := gomock.NewController()
    defer ctrl.Finish()
    http.MOCK().SetController(ctrl)
    http.EXPECT().Get(BASE_URL)
    downloader()
    // The rest to be written
}

テスト出力は次のとおりです。

エラー: '_et/http' のインストールに失敗しました: 終了ステータス 1 出力: パッケージを読み込めません: パッケージ _et/http: パッケージ http (chunked.go) とメイン (main_mock.go) が
/var/folders/z9/に見つかりましたql_yn5h550s6shtb9c5sggj40000gn/T/withmock570825607/パス/src/_et/http

Withmock はテストの問題の解決策になりますか? それを機能させるにはどうすればよいですか?

4

7 に答える 7

39

代わりに変数を使用するように関数定義を変更した場合:

var get_page = func(url string) string {
    ...
}

テストでオーバーライドできます。

func TestDownloader(t *testing.T) {
    get_page = func(url string) string {
        if url != "expected" {
            t.Fatal("good message")
        }
        return "something"
    }
    downloader()
}

ただし、オーバーライドする関数の機能をテストすると、他のテストが失敗する可能性があることに注意してください。

Go の作成者は、Go 標準ライブラリでこのパターンを使用して、コードにテスト フックを挿入し、テストを容易にします。

于 2014-06-24T02:00:23.433 に答える
9

私は次のようなことをします、

主要

var getPage = get_page
func get_page (...

func downloader() {
    dl_slots = make(chan bool, DL_SLOT_AMOUNT) // Init the download slot semaphore
    content := getPage(BASE_URL)
    links_regexp := regexp.MustCompile(LIST_LINK_REGEXP)
    matches := links_regexp.FindAllStringSubmatch(content, -1)
    for _, match := range matches{
        go serie_dl(match[1], match[2])
    }
}

テスト

func TestDownloader (t *testing.T) {
    origGetPage := getPage
    getPage = mock_get_page
    defer func() {getPage = origGatePage}()
    // The rest to be written
}

// define mock_get_page and rest of the codes
func mock_get_page (....

そして、私は_golangでは避けます。キャメルケースを使ったほうがいい

于 2015-05-11T06:55:04.253 に答える