How to mock a function from another file - go

I'm playing around with Golang and test cases in it, but it's almost completely different from other testing libraries in other languages (I'm with JS background)
In my file I have:
type MyHandler struct {
myBool bool
Person searchFile.Person
}
And lastly in my third file I have:
type Person interface {
searchFor(name string) (string, error)
}
In my main_test.go I have the following line:
h := &MyHandler{myBool: false} <- how can I mock the searchFor function in Golang

It's just an interface, so simply create a struct that implements the interface (and modify the interface so the method is exported, since it doesn't really make sense to have an unexported method in an interface):
type Person interface {
SearchFor(name string) (string, error)
}
type MockSearcher struct{}
func (m MockSearcher) SearchFor(name string) (string, error) {
return "mock name", nil
}
person := MockSearcher{}
h := &MyHandler{myBool: false, Person: person}

You can embed that interface !
package main
import (
"play.ground/sealed"
)
type sealedStruct struct {
sealed.Interface
}
func (s sealedStruct) sealed() {}
var j sealed.Interface = sealedStruct{}
func main() {
}
-- go.mod --
module play.ground
-- sealed/interface.go --
package sealed
type Interface interface {
sealed()
}
-- sealed/interface_test.go --
package sealed_test
import "test/d/sealed"
type sealedStruct struct {
sealed.Interface
}
func (s sealedStruct) sealed() {}
var j sealed.Interface = sealedStruct{}
https://play.golang.org/p/Ic_TnrLlF_u

Related

Why can't I call an interface with a collection of methods from the main package

I am really new to golang and I am trying to see how encapsulation really works in go.
I have the following structure
-- package a
-a_core.go
-a.go
-models.go
-- main.go
In models.go I have structs for request and responses for an api call,
a.go has an empty struct, which is private and a public interface, which I want to expose with various methods
a_core.go just has some business logic which would be called in my interface implementation
Then, I have a main.go where I just call the public interface.
code in a.go
package a
type myFunction struct{}
type MyFunc interface {
Create(myData *MyData) (*MyData, error)
Fetch(test string)
Delete(test string)
}
//Concrete implementations that can be accessed publicly
func (a *myFunction) Create(data *MyData) (*MyData, error) {
return nil, nil
}
func (a *myFunction) Fetch(test string) {
}
func (a *myFunction) Delete(test string) {
}
In main.go, I call the interface my first create the MyData pointer with values
data := &a.MyData{
/////
}
result, err := a.MyFunc.Create(data)
I get the following error when I do this,
too few arguments in call to a.MyFunc.Create
cannot use data (variable of type *a.MyData) as a.MyFunc value in argument to a.MyFunc.Create: missing method CreatecompilerInvalidIfaceAssign
Please what am I doing wrong?
Here is an example
Note that names in uppercase are public, in lowercase private (see https://tour.golang.org/basics/3 )
./go-example/main.go
package main
import "go-example/animal"
func main() {
var a animal.Animal
a = animal.Lion{Age: 10}
a.Breathe()
a.Walk()
}
./go-example/animal/animal.go
package animal
import "fmt"
type Animal interface {
Breathe()
Walk()
}
type Lion struct {
Age int
}
func (l Lion) Breathe() {
fmt.Println("Lion breathes")
}
func (l Lion) Walk() {
fmt.Println("Lion walk")
}

Casting using type assertion in golang

I understood that casting is being implemented in go using type assertion.
I'm trying to cast an object which is an instance of a struct that implements an interface.
My Code:
package main
import "fmt"
type Base interface {
Merge(o Base)
}
type Impl struct {
Names []string
}
func (i Impl) Merge (o Base) {
other, _ := o.(Impl)
i.Names = append(i.Names, other.Names...)
}
func main() {
impl1 := &Impl{
Names: []string{"name1"},
}
impl2 := &Impl{
Names: []string{"name2"},
}
impl1.Merge(impl2)
fmt.Println(impl1.Names)
}
Which outputs this:
[name1]
I expect the output to be:
[name1, name2]
Why this casting doesn't work? After debugging this it seems like that the other variable is empty.
You need to use a pointer method to modify the receiver's build.
func (i *Impl) Merge (o Base) {
other, _ := o.(*Impl)
i.Names = append(i.Names, other.Names...)
}
Playground: https://play.golang.org/p/7NQQnfJ_G6A

Why does method signature have to perfectly match interface method

I began to learn Go and have trouble understanding the following:
package main
import "fmt"
type I interface {
foo(interface {})
}
type S struct {}
func (s S) foo(i int) {
fmt.Println(i)
}
func main() {
var i I = S{}
i.foo(2)
}
This fails with:
cannot use S literal (type S) as type I in assignment:
S does not implement I (wrong type for foo method)
have foo(int)
want foo(interface {})
I don't understand why Go doesn't accept the foo(int) signature given the fact that int implements interface {}. Can anyone help with an explanation?
I think your understanding of interface isn't sound. Interface{} itself is a type. It consists of two things : underlying type and underlying value.
Golang doesn't have overloading. Golang type system matches by name and requires consistency in the types
So, when you are defining a function taking a interface type as a parameter:
foo(interface {})
This is a different function from a function taking int type:
foo(int)
So you should change the following line to
func (s S) foo(i interface{}) {
fmt.Println(i)
}
Or better yet to this:
type I interface {
foo()
}
type S struct {
I int
}
func (s S) foo() {
fmt.Println(s.I)
}
func main() {
var i I = S{2}
i.foo()
}
The error message itself is self-explaining:
"S does not implement I (wrong type for foo method)"
so S{} which is of S type cannot be used on the RHS of type I variable assignment.
To implement I interface, type S needs to define foo function with the exact same signature.
To achieve what you wanted, you can use empty interface as input parameter for your foo function in S and do type assertion
package main
import "fmt"
type I interface {
foo(interface {})
}
type S struct {}
func (s S) foo(i interface{}) {
if i, ok := i.(int); ok{
fmt.Println(i)
}
}
func main() {
var i I = S{}
i.foo(2)
i.foo("2")
}
Try it in go playground

how to get the method fields of a typed function (Go)

I'm wondering if it's possible to get the method fields from a typed function using reflection or by other means.
The problem that I'm trying to solve is that I have a method which accepts a function of specific type but I need to actually transport different types and based on the type provided to execute operations. I'm aware that I could use an interface{} value as receiver but I don't want to loose the type checking on the calling function ("GetIt")
package main
type ttp struct {
Coupons string
}
func (m ttp) GetIt(x string) {
if m.Coupons != "" {
print(m.Coupons)
}
}
func calculate(mth func(s string)){
//perform calculations and update the Coupon field
mth.Cupons = "one coupon" // is not working :(
// execute it again with the processed value
mth.GetIt() // is not working
}
func main() {
m := ttp{Coupons: "something"}
calculate(m.GetIt)
}
Play
well this does not answer your exact question but it should solve your problem and cleanup the logic: push the calculate method inside the type and use a interface
https://play.golang.org/p/On_AigRYW6
package main
import "fmt"
type Computer interface {
Compute(string)
}
type myp struct {
Coupons string
}
// myp implements Computer
func (m *myp) Compute(x string) {
m.GetIt(x)
fmt.Println("myp")
}
type ttp struct {
Various string
}
// ttp implements Computer
func (m *ttp) Compute(x string) {
m.GetIt(x)
fmt.Println("ttp")
}
func (m myp) GetIt(x string) {}
func (m ttp) GetIt(x string) {}
func main() {
m := &myp{Coupons: "something"}
t := &ttp{Various: "various stuff"}
var stuff = []Computer{m, t}
for _, c := range stuff {
c.Compute("s")
}
}

Private fields and methods for a struct

In the following test code I would like to have both mytype and the doPrivate method private, so that only members of mytype can access it, but not other types\functions in the scope of the mypackage package.
Can I do this in golang?
package mypackage
type mytype struct {
size string
hash uint32
}
func (r *mytype) doPrivate() string {
return r.size
}
func (r *mytype) Do() string {
return doPrivate("dsdsd")
}
Fields size and hash as well as the doPrivate method should be encapsulated and no other type should have access to them.
In Go, an identifier that starts with a capital letter is exported from the package, and can be accessed by anyone outside the package that declares it.
If an identifier starts with a lower case letter, it can only be accessed from within the package.
If you need members in a type to only be accessed by members of that type, you then need to place that type and its member functions in a separate package, as the only type in that package.
That's not how "privacy" works in Go: the granularity of privacy is the package.
If you really want only the members of mytype to access some fields, then you must isolate the struct and the functions in their own package.
But that's not the usual practice. Whether Go is OOP or not is debatable but clearly the practice isn't to encapsulate the code by a struct like you seem to want to do. Usually a package is small enough to be coherent: if you don't want to access fields from within the package, don't access them.
You can create an interface with the method you wish to expose and only access the object when wrapped into that interface.
package main
type mytype struct {
size string
hash uint32
}
// interface for exposed methods
type myinterface interface {
do() string
}
// constructor (optional)
func newMytype(size string, hash uint32) myinterface {
return &mytype{size, hash}
}
func (r *mytype) doPrivate() string {
return r.size
}
func (r *mytype) do() string {
return r.doPrivate()
}
func main() {
// with constructor
t := newMytype("100", 100)
t.do()
// t.doPrivate() // t.doPrivate undefined (type myinterface has no field or method doPrivate)
// without constructor
t2:= myinterface(&mytype{"100", 100})
t2.do()
// t.doPrivate() // t.doPrivate undefined (type myinterface has no field or method doPrivate)doPrivate)
}
https://play.golang.org/p/awjIIj8Kwms
You cannot do this in Go. Visibility is on a per package level only. But you may split your package into two.
In one module there can be any number of packages.
Public/Private works only across one package.
All public fields, methods and functions starts with uppercase char.
All private fields, methods and functions starts with lowercase char.
To add package to your module or program just create a lowercase folder and add package name to all files inside. Here is the example.
./main.go
./foo/foo.go
./foo/MyStruct.go
file ./foo/foo.go:
package foo
import "fmt"
func SomePublicFuncInFoo() {
somePrivateFuncInFoo()
}
func somePrivateFuncInFoo() {
fmt.Println("somePrivateFuncInFoo call")
}
file ./foo/MyStruct.go:
package foo
import "fmt"
type MyStruct struct {
MyPublicField string // starts with uppercase char
myPrivateField string // starts with lowercase char
}
func NewMyStruct(publicField string, privateField string) *MyStruct {
return &MyStruct{
MyPublicField: publicField,
myPrivateField: privateField,
}
}
func (self *MyStruct) SomePublicMethod() {
self.privateMethod()
}
func (self *MyStruct) privateMethod() {
fmt.Println("MyStruct", self.MyPublicField, self.myPrivateField)
}
file ./main.go:
package main
import (
"fmt"
"{your-module-name}/foo" // this line should be added by your IDE
)
func main() {
foo.SomePublicFuncInFoo()
myStruct := foo.NewMyStruct("string1", "string2")
fmt.Println("myStruct.MyPublicField=", myStruct.MyPublicField)
myStruct.SomePublicMethod()
}
You can have private variables and functions in Go, but the trick is that you simply don't define them in the struct. Bind them to the call stack of a closure, and simply don't return them.
package main
import (
"fmt"
)
type mytype struct {
Do func() string
}
func MyType(size string, hash uint32) mytype {
doPrivate := func() string {
return size
}
return mytype{
Do: func() string {
return doPrivate()
},
}
}
func main() {
instance := MyType("100", 100)
fmt.Println(instance.Do())
}

Resources