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
repo
di 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
repoMock
mempunyai signature yang sama dengan interfaceRepository
. Cek kode berikut. - parameter
lang
, di-inject dengan methodd.Called(lang)
- method
FetchMessage
mengembalikan 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
FetchMessage
yg defaultnya string "bzzzz" dengan string "lah". - Instance
theRepoMock
kemudian di-inject kegreeter
struct. - Perlu diingat, bahwa
greeter
struct itu sudah memiliki field Repo yang type-nyaRepository
. - Karena type-nya sudah sama, maka perilaku
FetchMessage
sudah 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