golang test spy incorrectly comparing equality - go

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)
}

Related

Uber Fx - Invoke

How do I get the following working?
To the lifecycle function, I need to pass 2 different implementations of Foo.
package main
import (
"context"
"fmt"
"go.uber.org/fx"
)
type Foo interface {
Print()
}
type Bar struct{}
func (b *Bar) Print() {
fmt.Println("I'm bar")
}
type Baz struct{}
func (b *Baz) Print() {
fmt.Println("I'm baz")
}
func foo() Foo {
return &Bar{}
}
func anotherFoo() Foo {
return &Baz{}
}
func main() {
workingStart() //This works
//nonWorkingStart() //This does not
}
func nonWorkingStart() {
app := fx.New(
fx.Provide(fx.Annotate(foo, fx.ResultTags(`name:"bar"`))),
fx.Provide(fx.Annotate(anotherFoo, fx.ResultTags(`name:"baz"`))),
//How to configure nonWorkingRun having 2 different foo's in its arguments?
fx.Invoke(nonWorkingRun),
)
if app.Err() != nil {
panic(fmt.Errorf("unable to bootstrap app: %w", app.Err()))
}
app.Run()
}
func workingStart() {
app := fx.New(
fx.Provide(foo),
fx.Invoke(workingRun),
)
if app.Err() != nil {
panic(fmt.Errorf("unable to bootstrap app: %w", app.Err()))
}
app.Run()
}
func nonWorkingRun(lifecycle fx.Lifecycle, foo Foo, anotherFoo Foo) {
lifecycle.Append(
fx.Hook{
OnStart: func(context.Context) error {
foo.Print()
anotherFoo.Print()
return nil
},
},
)
}
func workingRun(lifecycle fx.Lifecycle, foo Foo) {
lifecycle.Append(
fx.Hook{
OnStart: func(context.Context) error {
foo.Print()
return nil
},
},
)
}
I got it working implementing it the following way. Not sure if there are other ways other than using a struct holding a slice of Foo's and building that struct using fx.ParamTags
type FooSlices struct {
fooSlices []Foo
}
func fooSlices(foo, anotherFoo Foo) FooSlices {
return FooSlices{fooSlices: []Foo{foo, anotherFoo}}
}
func main() {
//workingStart()
nonWorkingStart()
}
func nonWorkingStart() {
app := fx.New(
fx.Provide(fx.Annotate(foo, fx.ResultTags(`name:"bar"`))),
fx.Provide(fx.Annotate(anotherFoo, fx.ResultTags(`name:"baz"`))),
fx.Provide(fx.Annotate(fooSlices, fx.ParamTags(`name:"bar"`, `name:"baz"`))),
fx.Invoke(nonWorkingRun),
)
if app.Err() != nil {
panic(fmt.Errorf("unable to bootstrap app: %w", app.Err()))
}
app.Run()
}
func nonWorkingRun(lifecycle fx.Lifecycle, fooSlices FooSlices) {
lifecycle.Append(
fx.Hook{
OnStart: func(context.Context) error {
for _, foo := range fooSlices.fooSlices {
foo.Print()
}
return nil
},
},
)
}
Collecting a slice of inputs is fairly hard to reason about, also not very extensible and goes against the spirit of what fx is "meant" to do (hide boilerplate code).
Just a small amount of refactors first
fx.Provide can take in a range of inputs and just needs to be called once
n implementations of foo requires only n-1 annotations, as the first one can be the raw type, and the remaining being the annotated types
avoid wrapping the panic and let it happen naturally if it happens; this would imply a syntax issue which can be mitigated prior to pushing the code
fx.New(
fx.Provide(
foo,
fx.Annotate(foo, fx.ResultTags(`name:"baz"`)),
),
fx.Invoke(toBeInvoked),
).Run()
type Params struct {
fx.In
Lifecycle fx.Lifecycle
Bar foo
Baz foo `name:"baz"`
}
func toBeInvoked(p Params) {
p.Lifecycle.Append(
fx.Hook{
OnStart: func(_ context.Context) error {
p.Bar.Print()
p.Baz.Print()
return nil
},
},
)
}
There are other ways to do this as well in fx, this one is a fairly common pattern.

Golang http handler testing with inner functions

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

Range over element of interface implementation

Let's supposed I've got the following interface and two structs that implement it:
type Tmp interface {
MyTmp() string
}
type MyStructA struct {
ArrayOfItems []int
}
func (a MyStructA) MyTmp() string {
return "Hello World"
}
type MyStructB struct {
ArrayOfItems []int
}
func (a MyStructB) MyTmp() string {
return "Hello World B"
}
As you notice both MyStructA and MyStructB implement Tmp and both have a property named ArrayOfItems. Using the interface signature, how could I iterate over that property which both have? Something similar to:
func (c ADifferentStruct) iterate(myTmp Tmp) {
for _, number := range myTmp.ArrayOfItems {
fmt.Println(number)
}
}
NOTE: I don't want to add another method to the interface (ie getter/setters) to process or to define ArrayOfItems
is this possible?
You need a method to return those items...
see this:
https://play.golang.org/p/rnH0riWKqRY
package main
import "fmt"
type Tmp interface {
MyTmp() string
Items() []int
}
type MyStructA struct {
ArrayOfItems []int
}
func (a MyStructA) MyTmp() string {
return "Hello World"
}
func (a MyStructA) Items() []int {
return a.ArrayOfItems
}
type MyStructB struct {
ArrayOfItems []int
}
func (a MyStructB) MyTmp() string {
return "Hello World B"
}
func (a MyStructB) Items() []int {
return a.ArrayOfItems
}
func iterate(tmp Tmp) {
for _, val := range tmp.Items() {
fmt.Println(val)
}
}
func main() {
a := MyStructA{[]int{1, 2, 3}}
b := MyStructA{[]int{-1, -2, -3}}
iterate(a)
iterate(b)
}

Testify mocking a single method

I'm pretty new to go. I'm trying to mock a single method of a struct using testify, but I don't know how to do it.
Here's the code:
type HelloWorlder interface {
SayHello() string
GetName() string
}
type HelloWorld struct{}
func (hw *HelloWorld) SayHello() string {
return fmt.Sprintf("Hello World from %s!", hw.GetName())
}
func (hw *HelloWorld) GetName() string {
return "se7entyse7en"
}
and here's the test:
type MockHelloWorld struct {
mock.Mock
HelloWorld
}
func (m *MockHelloWorld) GetName() string {
args := m.Called()
return args.String(0)
}
type SomeTestSuite struct {
suite.Suite
}
func (s *SomeTestSuite) TestMocking() {
mhw := new(MockHelloWorld)
mhw.On("GetName").Return("foo bar")
fmt.Println(mhw.SayHello())
}
The idea is to mock only the GetName method so that it prints Hello World from foo bar!. Is that possible?
For those familiar with Python, what I'm trying to achieve is similar to what the unittest.Mock class permits through the wraps argument.
UPDATE
The imported packages from testify are these:
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
Maybe this will help you.
package main
import (
"fmt"
"github.com/stretchr/testify/mock"
)
type userReader interface {
ReadUserInfo(int) int
}
type userWriter interface {
WriteUserInfo(int)
}
type UserRepository struct {
userReader
userWriter
}
type realRW struct{}
func (db *realRW) ReadUserInfo(i int) int {
return i
}
func (db *realRW) WriteUserInfo(i int) {
fmt.Printf("put %d to db.\n", i)
}
// this is mocked struct for test writer.
type MyMockedWriter struct {
mock.Mock
}
func (m *MyMockedWriter) ReadUserInfo(i int) int {
args := m.Called(i)
return args.Int(0)
}
func main() {
rw := &realRW{}
repo := UserRepository{
userReader: rw,
userWriter: rw,
}
fmt.Println("Userinfo is:", repo.ReadUserInfo(100))
repo.WriteUserInfo(100)
// when you want to write test.
fmt.Println("Begin test....................")
testObj := new(MyMockedWriter)
testObj.On("ReadUserInfo", 123).Return(250)
testRepo := UserRepository{
userReader: testObj,
userWriter: rw,
}
fmt.Println("Userinfo is:", testRepo.ReadUserInfo(123))
testRepo.WriteUserInfo(100)
}
// Output:
// Userinfo is: 100
// put 100 to db.
// Begin test....................
// Userinfo is: 250
// put 100 to db.
Good luck.

How to test dependency has been called correctly

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!

Resources