Package A
func Validate(){
db.CheckPresent() //how to mock this function which is in another package
return nil
}
I am writing test case in Golang to test a function which calls CheckPresent() function from another package. How to mock CheckPresent() fuction?
type Checker interface {
CheckPresent()
}
// mock
type checkerMock struct {
}
func (m checkerMock) CheckPresent() {
}
// production code
type handler struct {
db Checker
}
func New(db Checker) *handler {
return &handler{
db: db,
}
}
func (h handler) Validate() {
h.db.CheckPresent()
return nil
}
Related
I want to build a testing part for my http handlers, and I want to use the http handler functions how they are, but I want to have separate functions that mock the db part of the handling. What I have in mind is something like:
package main
import (
"log"
"testing"
)
// DB functions
type UserDBFunctions interface {
InsertUser() string
}
type UserDB struct {
}
func (u UserDB) InsertUser() string {
return "hello"
}
// http handler functions
type UserHandlerFunctions interface {
Register() string
}
type UserHandler struct {
userDb *UserDB
}
func newUserHandler() UserHandler {
return UserHandler{userDb: new(UserDB)}
}
func (u UserHandler) Register() string {
str := u.userDb.InsertUser()
return str + " world"
}
func main() {
var i UserHandlerFunctions = newUserHandler()
str := i.Register()
log.Println(str)
}
// test functions
type FakeUserDBFunctions interface {
InsertUser() string
}
type FakeUserDB struct {
}
func (u FakeUserDB) InsertUser() string {
return "bye"
}
func newFakeUserHandler() UserHandler {
return UserHandler{userDb: *UserDB(&FakeUserDB{})}
}
func TestRegisterUser(t *testing.T) {
t.Run("register user", func(t *testing.T) {
var i UserHandlerFunctions = newFakeUserHandler()
str := i.Register()
log.Println(str)
})
}
So the first interface is for the real db functions, then there is the http handler which calls the db function and below the main() function there should be the tests with a mockup of the db function. But this part doesn't work. How do I replace the real interface in the newUserHandler by a mockup.
I would really appreciate help. 😊
The UseHandler shall use UserDBFunctions instead of UserDB.
type UserHandler struct {
userDb UserDBFunctions
}
Here is the modified one https://play.golang.org/p/nLiaomKA2NH
First time posting a question here, sorry if the format is wrong. Do let me know how I could improve my question asking.
package main
type smallerInterface interface {
Problem() smallerRet
}
type biggerInterface interface {
Problem() biggerRet
}
type smallerRet interface {
Wait() bool
}
type biggerRet interface {
Wait() bool
Error() error
}
type ret struct{}
type sample struct{}
func (ret) Wait() bool {
return true
}
func (ret) Error() error {
return nil
}
func (sample) Problem() biggerRet {
return ret{}
}
func main() {
var first biggerInterface = sample{}
var second smallerInterface = sample{}
}
Demo of the problem can be viewed here https://play.golang.org/p/l0xdO03bBy7
Basically, is there a way to reconcile both smallerInterface and biggerInterface so sample can be assigned to a variable of type smallerInterface?
Concretely I would like to use smallerInterface for mocking in internal testing and receive biggerInterface from an external library in producton. As such it would be preferable to keep the smallerRet interface so I can keep the mock return value interface small, with sample being the production return value.
Additionally, is there a name for this problem or concept?
Thanks in advance!
You can try embedding the interfaces so that the sample can be assigned to type smallerInterface. I recreated your code as follows :
package main
import "fmt"
type smallerInterface interface {
biggerInterface
}
type biggerInterface interface {
Problem() biggerRet
}
type smallerRet interface {
Wait() bool
}
type biggerRet interface {
Wait() bool
Error() error
}
type ret struct{}
type sample struct{}
func (ret) Wait() bool {
return true
}
func (ret) Error() error {
return nil
}
func (sample) Problem() biggerRet {
return ret{}
}
func main() {
var first biggerInterface = sample{}
var second smallerInterface = sample{}
fmt.Println(first)
fmt.Println(second)
}
Output:
{}
{}
I am trying to use google/wire for dependency injection.
When I use wire check command in terminal, it's shows no provider found for *my_go_app.Listener, output of injector.
wire.go
// +build wireinject
package main
import (
"fmt"
"github.com/google/wire"
)
type Speaker interface {
Say()
}
type HelloSpeaker struct {
word string
}
func NewHelloSpeaker() *HelloSpeaker {
return &HelloSpeaker{
word: "Hello, World!!",
}
}
func (s *HelloSpeaker) Say() {
fmt.Printf("%s", s.word)
}
type Listener interface {
WhatIListened()
}
type SimpleListener struct {
speaker *Speaker
}
func NewSimpleListener(speaker *Speaker) *SimpleListener {
return &SimpleListener{
speaker: speaker,
}
}
func (l *SimpleListener) WhatIListened() {
(*l.speaker).Say()
}
func InitializeListener() *Listener {
wire.Build(
NewHelloSpeaker,
NewSimpleListener,
)
return nil
}
main.go
package main
func main() {
listener := InitializeListener()
(*listener).WhatIListened()
}
What I tried is below.
NewSimpleListener return *Listener, but &SimpleListener not match *Listener.
Use wire.Bind, but same error message.
SimpleListener not implements Listener?
It seems that wire is not smart enough to do automatic conversion.
wire.go
...
//change type of argument of speaker from *Speaker to Speaker
//don't want to create a new conversion method
func NewSimpleListener(speaker Speaker) *SimpleListener
...
func InitializeListener() Listener {
wire.Build(
NewHelloSpeaker, //*HelloSpeaker, HelloSpeaker doesn't implement Speaker interfaces, conversion is needed in next step
wire.Bind(new(Speaker),new(*HelloSpeaker)), //this binding can provide Speaker, not *Speaker
NewSimpleListener, //scenario as NewHelloSpeaker
//provide Listener, an extra method is needed if *Listener is wanted.
wire.Bind(new(Listener), new(*SimpleListener)),
)
return nil
}
main.go
...
listener := InitializeListener()
listener.WhatIListened()
...
In Go, how would I test that a mock dependency has been called in the correct way.
If I have a struct that takes a interface for a dependency, after injection I want to be able to test the original mock object has been called.
My current code in this example I can not see that the struct value has changed. If I change my code to pass by reference it triggers the error:
s.simpleInterface.Call undefined (type *SimpleInterface is pointer to interface, not interface)
type SimpleInterface interface {
Call()
}
type Simple struct {
simpleInterface SimpleInterface
}
func (s Simple) CallInterface() {
s.simpleInterface.Call()
}
type MockSimple struct {
hasBeenCalled bool
}
func (ms MockSimple) Call() {
ms.hasBeenCalled = true
}
func TestMockCalled(t *testing.T) {
ms := MockSimple{}
s := Simple{
simpleInterface: ms,
}
s.CallInterface()
if ms.hasBeenCalled != true {
t.Error("Interface has not been called")
}
}
I see three easy ways to fix this:
1- Change the signature of the Call method to receive a pointer to MockSimple, and when instantiating the Simple struct, give it the address of your mock:
func (ms *MockSimple) Call() {
ms.hasBeenCalled = true
}
func TestMockCalled(t *testing.T) {
ms := MockSimple{}
s := Simple{
simpleInterface: &ms,
}
s.CallInterface()
if ms.hasBeenCalled != true {
t.Error("Interface has not been called")
}
}
2- Not the cleanest solution, but still works. Use it if you really cant use #1. Declare "hasBeenCalled" somewhere else and change your MockSimple to hold a pointer to it:
type MockSimple struct {
hasBeenCalled *bool
}
func (ms MockSimple) Call() {
*ms.hasBeenCalled = true
}
func TestMockCalled(t *testing.T) {
hasBeenCalled := false
ms := MockSimple{&hasBeenCalled}
s := Simple{
simpleInterface: ms,
}
s.CallInterface()
if hasBeenCalled != true {
t.Error("Interface has not been called")
}
}
3- Probably a really bad solution: using globals, so I would only use it as a last resort (always avoid global state). Make "hasBeenCalled" a global and modify it from the method.
var hasBeenCalled bool
type MockSimple struct{}
func (ms MockSimple) Call() {
hasBeenCalled = true
}
func TestMockCalled(t *testing.T) {
ms := MockSimple{}
s := Simple{
simpleInterface: ms,
}
s.CallInterface()
if hasBeenCalled != true {
t.Error("Interface has not been called")
}
}
Cheers!
I'm in the process of learning go and am adapting a Java Game of Life example from testdouble. However, the test spy I have written incorrectly compares equality of my World struct - the test passes when it should fail, since output(world) is not being called. What am I doing incorrectly?
Test:
package gameoflife
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestZeroGenerations(t *testing.T) {
generatesSeedWorldStub := GeneratesSeedWorldStub{}
outputsWorldSpy := OutputsWorldSpy{}
conway := NewSimulatesConway(&generatesSeedWorldStub, &outputsWorldSpy)
seedWorld := World{}
conway.simulate()
correctWorld := outputsWorldSpy.wasOutputCalledWithWorld(seedWorld)
if !correctWorld {
t.Errorf("Output called with seed world, expected: %t, got: %t", true, correctWorld)
}
}
type GeneratesSeedWorldStub struct{}
func (gsw *GeneratesSeedWorldStub) generate() World {
return World{}
}
type OutputsWorldSpy struct {
outputCalledWithWorld World
}
func (ow *OutputsWorldSpy) output(world World) {
ow.outputCalledWithWorld = world
}
func (ow *OutputsWorldSpy) wasOutputCalledWithWorld(world World) bool {
return cmp.Equal(world, ow.outputCalledWithWorld)
}
Implementation:
package gameoflife
type SimulatesConway struct {
generatesSeedWorld GeneratesSeedWorld
outputsWorld OutputsWorld
}
func NewSimulatesConway(generatesSeedWorld GeneratesSeedWorld, outputsWorld OutputsWorld) SimulatesConway {
return SimulatesConway{generatesSeedWorld: generatesSeedWorld, outputsWorld: outputsWorld}
}
func (sc *SimulatesConway) simulate() {
// seedWorld := sc.generatesSeedWorld.generate()
// sc.outputsWorld.output(seedWorld)
}
type GeneratesSeedWorld interface {
generate() World
}
type OutputsWorld interface {
output(world World)
}
type World struct{}
When called outputsWorldSpy := OutputsWorldSpy{} golang assigned default value in outputsWorldSpy.outputCalledWithWorld = World{} and you assigned seedWorld := World{}. So they are same that's why test passed. If you want to handle that case, i suggest to use pointer.
type OutputsWorldSpy struct {
outputCalledWithWorld *World
}
func (ow *OutputsWorldSpy) output(world World) {
ow.outputCalledWithWorld = &world
}
func (ow *OutputsWorldSpy) wasOutputCalledWithWorld(world World) bool {
if ow.outputCalledWithWorld == nil {
return false
}
return cmp.Equal(world, *ow.outputCalledWithWorld)
}