Golang http handler testing with inner functions - go

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

Related

How can I assign a variable of type interfaceA with a method that returns a broader interface, to a variable of type interfaceB with narrower return

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:
{}
{}

Why wire can't generate wire_gen.go?

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()
...

How do I mock a function from another package?

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
}

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.

golang test spy incorrectly comparing equality

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

Resources