Catatan ini merupakan sambungan dari Kegunaan Interface. Kode-kode yang digunakan di page ini terkait dengan page tersebut.
Coba perhatikan kode berikut:
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGreet(t *testing.T) {
repo := NewRepository()
service := NewGreeter(repo, "en")
msg := service.Greet()
assert.Equal(t, "bzzzz", msg)
}Simpan kode di atas menjadi file main_test.go.
Kode diatas bertujuan untuk membandingkan string "bzzzz" dengan nilai dari method Greet().
Jalankan test:
go test
Hasilnya:
PASS
ok mock 0.003s
Sebenarnya tidak ada masalah testing menggunakan cara di atas. Hasilnya sudah PASS.
Hanya saja, jika kasusnya kompleks, maka perlu usaha lagi.
Misalnya saja:
- Apa yang terjadi jika
repodi atas ternyata harus terkoneksi ke database? - Sementara itu, kita tidak bisa mengakses database tersebut. Karena tidak punya password dan username-nya, misalnya.
- Padahal, yang kita inginkan sebenarnya hanya ingin mengetahui, fungsi
Greet()ini sudah sesuai dengan ekspektasi apa belum.
Di sinilah kegunaan mock: mengganti nilai yang dibutuhkan Greet() dengan cara mengontrol implementasi method yang ada di Repository.
Perhatikan kode berikut:
package main
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// Inisialisasi Mock
type repoMock struct {
mock.Mock
}
func (d *repoMock) FetchMessage(lang string) (string, error) {
args := d.Called(lang)
return args.String(0), args.Error(1)
}
// Penggunaan mock
func TestMockMethodWithArgs(t *testing.T) {
theRepoMock := repoMock{}
// if FetchMessage("id") is called, then return "lah"
theRepoMock.On("FetchMessage", "id").Return("lah", nil)
g := greeter{&theRepoMock, "id"}
assert.Equal(t, "lah", g.Greet())
theRepoMock.AssertExpectations(t)
}- Perhatikan bahwa struct
repoMockmempunyai signature yang sama dengan interfaceRepository. Cek kode berikut. - parameter
lang, di-inject dengan methodd.Called(lang) - method
FetchMessagemengembalikan nilai yang di-inisialisasi olehreturn args.String(0), args.Error(1).
Perhatikan: signature type-nya harus sama.
- Method
theRepoMock.On("FetchMessage", "id").Return("lah", nil)dibuat untuk mengontrol dan mengubah perilaku methodFetchMessage. - Method tersebut mengganti balikan
FetchMessageyg defaultnya string "bzzzz" dengan string "lah". - Instance
theRepoMockkemudian di-inject kegreeterstruct. - Perlu diingat, bahwa
greeterstruct itu sudah memiliki field Repo yang type-nyaRepository. - Karena type-nya sudah sama, maka perilaku
FetchMessagesudah diganti dengan definsi baru.
Jalankan perintah ini:
go test -v
Hasilnya:
=== RUN TestMockMethodWithArgs
main_test.go:39: PASS: FetchMessage(string)
--- PASS: TestMockMethodWithArgs (0.00s)
PASS
ok mock 0.003s
Kode sumber catatan ini bisa diakses di tautan berikut