Can't mock struct for testing - go

Trying to mock struct for testing. But following code has an error:
./test.go:32:17: cannot use NewClass() (type *Class) as type mockClass in return argument:
*Class does not implement mockClass (wrong type for Query method)
have Query() *Iterator
want Query() mockIterator
Why I can't do that?
func NewClass() *Class {
return &Class{}
}
type Class struct{}
func (Class) Query() *Iterator {
return &Iterator{}
}
type Iterator struct{}
func (Iterator) Next() error {
return nil
}
type mockClass interface {
Query() mockIterator
}
type mockIterator interface {
Next() error
}
var newMock = func() mockClass {
return NewClass()
}
In the test I want to assign to newMock something like:
newMock = funcr() mockClass {
return &fakeClass{}
}
The structs Class and Iterator are not under my control. Those structs come from external library.

Create an interface that expresses business logic that your component needs. Do not use any 3rd party types.
Use that interface in your business logic.
Create an implementation of this interface wrapping 3rd party library and pass it to your component in main.go, which is a good place to wire/inject various system components.
That way you can easily mock your interface and change the implementation for another if one day you decide not to use this 3rd party library.
If for some reason you are tied to this library and there is no way to create an interface not referencing 3rd party types, then have a look at the Can I mock out library code with a nested interface?

Related

golang struct not implementing interface?

I am a beginner with go so bear with me on this. I have an interface defined as the following:
type DynamoTable interface {
Put(item interface{}) interface{ Run() error }
}
also I have a Repo struct like so:
type TenantConfigRepo struct {
table DynamoTable
}
and i have a struct dynamo.Table which has a Put function defined like so:
func (table dynamo.Table) Put(item interface{}) *Put
and the Put struct has a Run function as follows:
func (p *Put) Run() error
What I am trying to do is have a generic DynamoTable interface which will then be used for mocking and unit tests. however this is causing an issue with creating a new Repo:
func newDynamoDBConfigRepo() *TenantConfigRepo {
sess := session.Must(session.NewSession())
db := dynamo.New(sess)
table := db.Table(tableName) //=> this returns a type dynamo.Table
return &TenantConfigRepo{
table: table,
}
}
This however is throwing an error like so
cannot use table (variable of type dynamo.Table) as DynamoTable value in struct literal: wrong type for method Put (have func(item interface{}) *github.com/guregu/dynamo.Put, want func(item interface{}) interface{Run() error})
this is very strange for me because from what i see is the interface that has a Run() error should be sufficient for the Put struct since it has the same signature. I am not sure what i am doing wrong here.
Thanks!.
wrong type for method Put (have func(item interface{}) *github.com/guregu/dynamo.Put, want func(item interface{}) interface{Run() error})
your function returns a *Put. The interface expects an interface{Run() error}. A *Put might satisfy this interface, but they're still different types. A function signature returning a type that satisfies that interface is not interchangeable with a function signature returning that interface.
So, start by giving your interface a name. We refer to it in 2 places, and you should avoid anonymous interface (and struct) definitions because they have no inherent benefit and make your code more verbose and less DRY.
type Runner interface{
Run() error
}
Now update DynamoTable to use that interface
type DynamoTable interface {
Put(item interface{}) Runner
}
You say dynamo.Table is outside of your control. But you can create a new type equal to dynamo.Table and then override the put method.
In overridden method, we'l cast our dynamoTable back to dynamo.Table, call the original dynamo.Table.Put, and then return the result.
type dynamoTable dynamo.Table
func (table *dynamoTable) Put(item interface{}) Runner {
return (*dynamo.Table)(table).Put(item)
}
dynamo.Table Can still return a *Put because *Put implements Runner. The return value will be Runner and the underlying type will be *Put. Then the interface will be satisfied, and that error will be fixed.
https://go.dev/play/p/y9DKgwWbXOO illustrates how this retype and override process works.

Refactoring method to be part of an interface

I am an ex python dev sometimes struggling with the explicit nature of Go.
I am trying here to refactor some code in order to be able move a method from one structure to be part of an interface.
But the process seems weird to me, I wish to confirm I am not doing something incorrectly.
I have the following interfaces, structure and methods:
type Executing interface {
Execute()
}
type MyExecuter struct {
attribut1 string
}
//The function I wish to move
func (exe1 *MyExecuter) format() string {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
func (exe1 *MyExecuter) Execute() {
//Executing
fmt.Println(exe.format())
}
func GetExecuter () Executer{
return MyExecuter{attribut1: "test"}
}
So here I have a generic interface Execute, this interface will be accessed by the object returned by the GetExecuter method.
Now, as part of the implementation of one of my Executer, I want to move the Format method as part of an interface.
So I am doing the following:
type Formatting interface {
format() string
}
type Formatter struct {}
func (formatter *Formatter) format(exe1 *MyExecuter) (string) {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
So I create a new interface, a new empty structure, and update my function to take as attribute my previous structure.
While this seems to work, it seems to me this is a bit convoluted. Specially the part where I need to add a reference to my initial object as attribute of the method. Am I doing something wrong here, or this is the right way?
Your Executer implementation already implements the Formatting interface:
type Executing interface {
Execute()
}
type Formatting interface {
format() string
}
func (exe1 MyExecuter) format() string {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
func (exe1 MyExecuter) Execute() {
//Executing
fmt.Println(exe.format())
}
v:=MyExecuter{}
// Here, v implements Executing and Formatting interfaces
One thing to note here: Your code shows pointer receivers. That means the methods are defined for *MyExecuter, but not for MyExecuter. So you have to pass pointers to the struct instance for this to work. Or, as I did above, use the value receivers so the methods are defined for both MyExecuter and *MyExecuter.

How to call an embedded struct method of an object passed as interface?

My scenario requires the user to embed a base struct and implement an interface.
Then, an instance of that struct should be passed to a function. The function needs to call a method of the base struct. This fails
// Given base struct and interface
type Interface interface {
Do()
}
type BaseStruct struct {
i int
s string
}
func (*b BaseStruct) Stuff() {}
// The user needs to create a struct that embeds BaseStruct and to implement Interface:
type CustomStruct struct {
*BaseStruct
}
func (*c CustomStruct) Do() {}
// The user now instantiates the struct and needs to call a function
inst := CustomStruct{}
SomePackageFun(&inst)
// The below function receives the custom struct, and must call the base struct's method, but this fails
func SomePackageFunc(i Interface) {
// declaring the function with Interface works but I can't call the methods of BaseStruct
i.Stuff() // not recognized by the compiler
}
If you want to be able to call a method on a variable of an interface type, you should add that method to the interface. Methods that come from embedded structs count for the purpose of satisfying interfaces. To call anything that isn't part of the interface, you have to assert to a concrete type (or a different interface type that has that method), which defeats the point.

Interface and Implementation

In following code snippet -
type Input interface {
Name() string
}
type Abc interface {
Do(Input)
}
type InputImpl struct {
}
func (InputImpl) Name() string {
return "sample-impl"
}
type AbcImpl struct {
}
func (abcImpl *AbcImpl) Do(input Input){
// do something
}
AbcImpl struct is an implementation of Abc interface, but changing last function like this -
func (abcImpl *AbcImpl) Do(input InputImpl){
// do something
}
Now the AbcImpl is not implementing Abc anymore, though InputImpl is implementing Input interface !
Am I missing something or it's compulsory to have exact same signature (not event Impls) as the interface to be a legitimate implementation?
Yes, you do have to follow the method signature you specified.
If you don't follow the signature, it will not be called "implementing".
an example: interface example
from tour of Go: There is no explicit declaration of intent, no "implements" keyword.
It is compulsory to use the very exact same signature when implementing an interface in Go. You can't implement it otherwise.

How to match private struct types using Ginkgo and Gomega?

Assume that I have a function called GetQueue with GoLang and depends on the configuration, it would return different types of queue implementations.
func GetQueue(config string) *service.Queue {
switch(config):
case "A":
return &QueueA.NewQueue{...}
case "B":
return &QueueB.NewQueue{...}
...
}
The service.Queue is an interface. And both QueueA and QueueB are implementations for this interface. The QueueA.go looks like:
type service struct {
...
}
function NewService() *service.Queue {
return &service{}
}
I'd like to write a unit test for the GetQueue function (which is defined outside of the service package) and I would like to verify the returned types are as expected. However, both QueueA.sevice and QueueB.service are private structs. So how can I verify the returned types are the expected ones?

Resources