2013-11-04 194 views
4

下面是我編寫的用於從mongodb中檢索文檔的處理程序。
如果找到文檔,我們將相應地加載和渲染模板。 如果失敗,它會重定向到404單元測試golang處理程序

func EventNextHandler(w http.ResponseWriter, r *http.Request) { 

    search := bson.M{"data.start_time": bson.M{"$gte": time.Now()}} 
    sort := "data.start_time" 
    var result *Event 
    err := db.Find(&Event{}, search).Sort(sort).One(&result) 
    if err != nil && err != mgo.ErrNotFound { 
     panic(err) 
    } 
    if err == mgo.ErrNotFound { 
     fmt.Println("No such object in db. Redirect") 
     http.Redirect(w, r, "/404/", http.StatusFound) 
     return 
    } 

    // TODO: 
    // This is the absolute path parsing of template files so tests will pass 
    // Code can be better organized 
    var eventnext = template.Must(template.ParseFiles(
     path.Join(conf.Config.ProjectRoot, "templates/_base.html"), 
     path.Join(conf.Config.ProjectRoot, "templates/event_next.html"), 
    )) 

    type templateData struct { 
     Context *conf.Context 
     E *Event 
    } 

    data := templateData{conf.DefaultContext(conf.Config), result} 

    eventnext.Execute(w, data) 

} 

手動嘗試了這一點,一切都很正常。

但是,我似乎無法得到這個通過我的單元測試。在相應的測試文件中,這是我的測試代碼,用於嘗試加載我的EventNextHandler

func TestEventNextHandler(t *testing.T) { 

    // integration test on http requests to EventNextHandler 

    request, _ := http.NewRequest("GET", "/events/next/", nil) 
    response := httptest.NewRecorder() 

    EventNextHandler(response, request) 

    if response.Code != http.StatusOK { 
     t.Fatalf("Non-expected status code%v:\n\tbody: %v", "200", response.Code) 
    } 

} 

該測試失敗,該行聲明EventNextHandler(response, request)

而在我的錯誤消息中,它指的是我的處理程序代碼中的行err := db.Find(&Event{}, search).Sort(sort).One(&result)

完全錯誤的訊息: -

=== RUN TestEventNextHandler 
--- FAIL: TestEventNextHandler (0.00 seconds) 
panic: runtime error: invalid memory address or nil pointer dereference [recovered] 
    panic: runtime error: invalid memory address or nil pointer dereference 
[signal 0xb code=0x1 addr=0x8 pc=0x113eb8] 

goroutine 4 [running]: 
testing.func·004() 
    /usr/local/go/src/pkg/testing/testing.go:348 +0xcd 
hp/db.Cursor(0xc2000c3cf0, 0xc2000fb1c0, 0x252d00) 
    /Users/calvin/gopath/src/hp/db/db.go:57 +0x98 
hp/db.Find(0xc2000c3cf0, 0xc2000fb1c0, 0x252d00, 0xc2000e55c0, 0x252d00, ...) 
    /Users/calvin/gopath/src/hp/db/db.go:61 +0x2f 
hp/event.EventNextHandler(0xc2000e5580, 0xc2000a16a0, 0xc2000c5680) 
    /Users/calvin/gopath/src/hp/event/controllers.go:106 +0x1da 
hp/event.TestEventNextHandler(0xc2000d5240) 
    /Users/calvin/gopath/src/hp/event/controllers_test.go:16 +0x107 
testing.tRunner(0xc2000d5240, 0x526fe0) 
    /usr/local/go/src/pkg/testing/testing.go:353 +0x8a 
created by testing.RunTests 
    /usr/local/go/src/pkg/testing/testing.go:433 +0x86b 

goroutine 1 [chan receive]: 
testing.RunTests(0x3bdff0, 0x526fe0, 0x1, 0x1, 0x1, ...) 
    /usr/local/go/src/pkg/testing/testing.go:434 +0x88e 
testing.Main(0x3bdff0, 0x526fe0, 0x1, 0x1, 0x532580, ...) 
    /usr/local/go/src/pkg/testing/testing.go:365 +0x8a 
main.main() 
    hp/event/_test/_testmain.go:43 +0x9a 

什麼是寫我的測試正確的方法是什麼?要考慮到從mongodb中檢索不到任何東西並應用斷言來驗證該情況,從而編寫驗證測試的情況。

+0

db是如何定義和初始化的?如果在測試過程中沒有初始化,那就是你的問題。如果你想要一個更簡單的方法來爲測試的參數化處理器,可能將它實現爲Handler類型而不是處理函數,並使數據庫連接成爲類型的成員。 –

+0

是的。這是問題所在。弄清楚了。謝謝! :-p –

+0

順便說一下,您可以考慮使用[GoConvey](https://github.com/smartystreets/goconvey)來使Go測試更容易。該設置只需在您的任何測試用例中進行一次。 – Matt

回答

5

看來我沒有在我的測試中初始化db。就像一個類似於所有其他語言的單元測試框架的「設置」步驟。

我必須確保我的db包已導入,然後實現兩行連接到數據庫並註冊索引。

func TestEventNextHandler(t *testing.T) { 

    // set up test database 

    db.Connect("127.0.0.1", "test_db") 
    db.RegisterAllIndexes() 

    // integration test on http requests to EventNextHandler 

    request, _ := http.NewRequest("GET", "/events/next/", nil) 
    response := httptest.NewRecorder() 

    EventNextHandler(response, request) 

    if response.Code != 302 { 
     t.Fatalf("Non-expected status code %v:\n\tbody: %v", "200", response.Code) 
    } 

}