22/07/2020 - GO
Bu örnekte bir fonksiyonu test edeceğiz ama onun sahte halini (mock) kullanarak. Mock önemlidir çünkü bazen belirli bir nedenden dolayı belirli bir işlevin gerçek mantığını çalıştırmak istemeyiz.
go get github.com/vektra/mockery/v2/.../
komutunu kullanarak mockery
dosyasını OS içine yükleyin. Bu komut ayrıca go.mod/sum
dosyalarına kendisi ile alakalı girdiler ekler ama siz bunları kaldırabilirsiniz çünkü go get -u http://github.com/stretchr/testify
komutunu çalıştırmak yeterli olacaktır.
package file
import (
"image"
"mime"
"os"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
)
type Manager interface {
Mime(path string) (string, error)
}
type Image struct {}
func (Image) Mime(path string) (string, error) {
fil, err := os.Open(path)
if err != nil {
return "", err
}
defer fil.Close()
_, mim, err := image.DecodeConfig(fil)
if err != nil {
return "", err
}
return mime.TypeByExtension("." + mim), nil
}
./internal/file/file.go
dosyasında Manager
interface var ve biz bunun mock hali olan ./internal/file/mocks/manager.go
dosyasını yaratıyoruz.
$ mockery --name Manager --dir ./internal/file/ --output ./internal/file/mocks --filename manager.go
22 Jul 20 10:21 BST INF Starting mockery dry-run=false version=(devel)
22 Jul 20 10:21 BST INF Walking dry-run=false version=(devel)
22 Jul 20 10:21 BST INF Generating mock dry-run=false interface=Manager qualified-name=github.com/you/client/internal/file version=(devel)
package file
import (
"fmt"
"testing"
"github.com/you/client/internal/file/mocks"
"github.com/stretchr/testify/assert"
)
func TestFile_Mime(t *testing.T) {
mockFile := &mocks.Manager{}
t.Run("file not found error", func(t *testing.T) {
mockFile.
On("Mime", "some-file.png").
Once().
Return("", fmt.Errorf("file not found"))
mim, err := mockFile.Mime("some-file.png")
assert.Empty(t, mim)
assert.Error(t, err, "file not found")
})
t.Run("config decoding error", func(t *testing.T) {
mockFile.
On("Mime", "some-file.png").
Once().
Return("", fmt.Errorf("config error"))
mim, err := mockFile.Mime("some-file.png")
assert.Empty(t, mim)
assert.Error(t, err, "config error")
})
t.Run("successfully getting mime", func(t *testing.T) {
mockFile.
On("Mime", "some-file.png").
Once().
Return("image/png", nil)
mim, err := mockFile.Mime("some-file.png")
assert.Equal(t, "image/png", mim)
assert.NoError(t, err)
})
}
$ go test -v -run TestFile_Mime ./internal/file/
=== RUN TestFile_Mime
=== RUN TestFile_Mime/file_not_found_error
=== RUN TestFile_Mime/config_decoding_error
=== RUN TestFile_Mime/successfully_getting_mime
--- PASS: TestFile_Mime (0.00s)
--- PASS: TestFile_Mime/file_not_found_error (0.00s)
--- PASS: TestFile_Mime/config_decoding_error (0.00s)
--- PASS: TestFile_Mime/successfully_getting_mime (0.00s)
PASS
Mac'te Homebrew ile mockery'yi yükleyebilirsiniz. Ayrıca, artık koddaki arayüzlere mockery ile ilgili komutları eklemeniz gerekmiyor. Tüm komut bayraklarını görmek için mockery --help
komutunu çalıştırabilirsiniz, ancak aşağıdakiler en çok kullanılanlardır.
--keeptree: Matches the actual package structure for the mock files
--inpackage: Uses the package name rather than "mocks"
--exported: Creates exported versions of unexported interfaces
--all: Creates mocks for all interfaces in all sub directories
--case=snake: Uses snake case for the file names
-- In root
- Runs through all interfaces in the codebase and puts mocks in root level "mocks" folder.
$ mockery --keeptree --inpackage --exported --all --case=snake
-- In package (classic)
- Runs through all interfaces in a package folder and puts mocks in "mocks" folder of same package folder.
$ mockery --exported --all --case=snake --dir=payment/ --output=payment/mocks
If you prefer running a common command $ go generate ./...
to generate all mocks in one-go, you can try version below.
//go:generate mockery --exported --case snake --name Doer
type interface Doer {
...