Jika kita periksa coverage test, pada file handlers_test.go, masih ada yang tercover, yaitu bagian render. Kita akan buat test untuk melakukan rendering bad template dengan menggunakan testdata.
Dengan menggunakan testdata, akan memudahkan melakukan testing tanpa harus menyentuh realdata.
Pertama kita perlu pindahkan dulu variable templatePath dari file handlers_test.go pada fungsi Test_application_handlers ke file setup_test.go
package main
import (
"os"
"testing"
)
var app application
func TestMain(m *testing.M) {
templatePath = "./../../templates/"
app.Session = getSession() //tambahkan session pada modul test
os.Exit(m.Run())
}
Buat direktori testdata didalam cmd/web.
Perhatian: nama folder harus testdata. Dengan menggunakan folder khusus ini, saat build aplikasi akan diabaikan.
Kemudian buat file templates cmd/web/testdata/bad.page.gohtml, yang isinya dicopy dari home.page.gohtml dengan sedikit modifikasi.
{{template "base" .}}
{{define "content"}}
<div class="container">
<div class="row">
<div class="col">
<h1 class="mt-3">Home Page</h1>
<hr>
<form action="/login" method="post">
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" name="email">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<hr>
<small>{{$nonExistVar}}</small>
</div>
</div>
</div>
{{end}}
Karena kita menggunakan base template, buat juga file cmd/web/testdata/base.layout.gohtml, yang isinya persis sama dengan templates/base.layout.gohtml.
Langkah terakhir adalah membuat fungsi test, buka file cmd/web/handlers_test.go, lalu tambahkan fungsi untuk test bad template, pada tutorial digunakan nama fungsi TestApp_renderWBadTemplate.
package main
import (
"context"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func Test_application_handlers(t *testing.T) {
var theTests = []struct {
name string
url string
expectedStatusCode int
}{
{"home", "/", http.StatusOK},
{"404", "/qwerty", http.StatusNotFound},
}
routes := app.routes()
//create a test server
ts := httptest.NewTLSServer(routes)
defer ts.Close()
//testing
for _, e := range theTests {
resp, err := ts.Client().Get(ts.URL + e.url)
if err != nil {
t.Log(err)
t.Fatal(err)
}
if resp.StatusCode != e.expectedStatusCode {
t.Errorf("for %s: expected status %d, but got %d", e.name, e.expectedStatusCode, resp.StatusCode)
}
}
}
func TestAppHome(t *testing.T) {
var tests = []struct {
name string
putInSession string
expctedHTML string
}{
{"First Visit", "", "<small>Session:"},
{"Second Visit", "skillplus", "<small>Session: skillplus"},
}
for _, e := range tests {
req, _ := http.NewRequest("GET", "/", nil)
req = addCtxSessToReq(req, app)
_ = app.Session.Destroy(req.Context())
if e.putInSession != "" {
app.Session.Put(req.Context(), "test", e.putInSession)
}
rr := httptest.NewRecorder()
handler := http.HandlerFunc(app.Home)
handler.ServeHTTP(rr, req)
//check status code
if rr.Code != http.StatusOK {
t.Errorf("TestAppHome: returned wrong status code, expected 200 but got %d", rr.Code)
}
body, _ := io.ReadAll(rr.Body)
if !strings.Contains(string(body), e.expctedHTML) {
t.Errorf("%s: did not find %s in response body", e.name, e.expctedHTML)
}
}
}
func TestApp_renderWBadTemplate(t *testing.T) {
templatePath = "./testdata/"
req, _ := http.NewRequest("GET", "/", nil)
req = addCtxSessToReq(req, app)
rr := httptest.NewRecorder()
err := app.render(rr, req, "bad.page.gohtml", &TemplateData{})
if err == nil {
t.Error("Expected error from bad template, but did not")
}
templatePath = "./../../templates/"
}
func addCtxSessToReq(req *http.Request, app application) *http.Request {
req = req.WithContext(context.WithValue(req.Context(), contextUserKey, "unknown"))
ctx, _ := app.Session.Load(req.Context(), req.Header.Get("X-Session"))
return req.WithContext(ctx)
}
Sampai disini kita sudah mempelajari cara melakukan testing untuk session. Pada modul selanjutnya kita akan mempelajari post testing.