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()
...
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
In Go, how to define an interface using another interface?
Here is an example:
package main
import (
"fmt"
)
// Interfaces
type Message interface {
Read() string
}
type MessageReader interface {
ReceiveMessages([]Message)
}
// Structs
type SQSMessage struct {
Content string
}
type SQSMessageReader struct {
Name string
}
// Implements
func (reader *SQSMessageReader) ReceiveMessages([]SQSMessage) {
}
func (msg *SQSMessage) Read() string {
return msg.Content
}
// A function needs a reader interface
func FuncNeedsReader(MessageReader) {
fmt.Println("get reader")
}
func main() {
var reader SQSMessageReader
FuncNeedsReader(reader)
}
I got error:
./prog.go:40:17: cannot use reader (type SQSMessageReader) as type MessageReader in argument to FuncNeedsReader:
SQSMessageReader does not implement MessageReader (wrong type for ReceiveMessages method)
have ReceiveMessages([]SQSMessage)
want ReceiveMessages([]Message)
Do anyone know if this design is conflicting with Go's design?
I know we have "accept interfaces, return structs"
So I also tried https://play.golang.org/p/qdGaKRYAqw7, but still fail with similar error.
I see two problems here.
First:
You have defined your MessageReader interface as:
type MessageReader interface {
ReceiveMessages([]Message)
}
But you have defined your ReceiveMessages method on SQSMessageReader like this:
func (reader *SQSMessageReader) ReceiveMessages([]SQSMessage) {
}
Because it takes an []SQSMessage parameter rather than []Message, it does not implement the MessageReader interface. You would need to write:
func (reader *SQSMessageReader) ReceiveMessages([]Message) {
}
Second:
You have written:
func main() {
var reader SQSMessageReader
FuncNeedsReader(reader)
}
But ReceiveMessages has a pointer receiver (func (reader *SQSMessageReader) ReceiveMessages...), so you would need:
func main() {
var reader SQSMessageReader
FuncNeedsReader(&reader)
}
With these two changes, your code builds without errors.
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'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.
I am a new to golang. I need to design a function to create object of differing types based on input. But I failed to figure out how to design the interface. Here comes my code:
package main
import (
"fmt"
)
type AA struct{
name string
}
func (this *AA) say(){
fmt.Println("==========>AA")
}
type BB struct{
*AA
age int
}
func (this *BB) say(){
fmt.Println("==========>BB")
}
func ObjectFactory(type int) *AA {
if type ==1 {
return new(AA)
}else{
return new(BB)
}
}
func main() {
obj1 := ObjectFactory(0)
obj1.say()
obj2 := ObjectFactory(0)
obj2.say()
}
The compiler tells me error no matter I ask ObjectFactory return *AA or interface{}. How can I make it work?
First off, using type as a variable name is disallowed in go (see the spec). That is your first problem.
The return type of object factory is *AA. This means that it can only return variables of type *AA, which causes the return of type of BB to fail. As defined in the spec, go doesn't have type inheritance, just struct embedding.
If you create an interface called sayer, you can use that instead of *AA in your ObjectFactory function.
type sayer interface {
say()
}
You probably want to use this interface when trying to get multiple dispatch (as demonstrated in the code below (see on play.golang.org as well).
Try this code:
package main
import (
"fmt"
)
type sayer interface {
say()
}
type AA struct{
name string
}
func (this *AA) say(){
fmt.Println("==========>AA")
}
type BB struct{
*AA
age int
}
func (this *BB) say(){
fmt.Println("==========>BB")
}
func ObjectFactory(typeNum int) sayer {
if typeNum ==1 {
return new(AA)
}else{
return new(BB)
}
}
func main() {
obj1 := ObjectFactory(1)
obj1.say()
obj2 := ObjectFactory(0)
obj2.say()
}