I am trying to mock an struct method in test cases but it is not working.
I want to mock Validate method here:
`
package main
import (
"fmt"
)
type DemoInterface interface {
Inc(int) (int, error)
Validate(int) error
}
type DemoStruct struct{}
func (l DemoStruct) Inc(num int) (int, error) {
err := l.Validate(num)
if err != nil {
return 0, err
}
num = num + 100
return num, nil
}
func (l DemoStruct) Validate(num int) error {// SOME DB LOGIC IS HERE WHICH I CAN NOT POST at Stackoverflow
if num > 100 {
return fmt.Errorf("INVALID NUM %v", num)
}
return nil
}
func main() {
s, err := DemoStruct{}.Inc(10)
if err != nil {
fmt.Println(err)
}
fmt.Println(s)
}
`
My test cases:
package main
import (
"fmt"
"testing"
)
const (
SUCCESS = "SUCCESS"
ERROR = "ERROR"
)
type MockDemoStruct struct {
DemoStruct
functionality string
}
func (m MockDemoStruct) Validate(num int) error {
switch m.functionality {
case SUCCESS:
return nil
case ERROR:
fmt.Errorf("MOCK ERROR %v", num)
}
return fmt.Errorf("MOCK ERROR %v", num)
}
func TestPath(t *testing.T) {
t.Run("ERROR", func(t *testing.T) {
ls := MockDemoStruct{DemoStruct{}, ERROR}
res, err := ls.Inc(110)
expected := fmt.Errorf("MOCK ERROR %v", 10)
if err != expected {
t.Errorf("NOT MATCH %v %v", err, expected)
//NOT MATCH INVALID NUM 110 MOCK ERROR 10
}
fmt.Println(res)
})
}
Here MockDemoStruct.Validate is not being called.
I am getting INVALID NUM 110 from Validate, but it should be MOCK ERROR 110
In this case the method Inc in the DemoStruct calls the method l.Validate where l is a DemoStruct. The reciever of that method is explicitly a DemoStruct. So the MockDemoStruct.Validate method will not be called.
Go does not have inheritance as you assumed here in your code. You can not override the method of the DemoStruct. The MockDemoStruct composes the DemoStruct. To actually test this method, I suggest passing the DemoStruct a db interface, which can be mocked in your test.
I think you also need to implement 'Inc' receiver for 'MockDemoStruct', here you trying to overuse the inheritance property of struct, looks like GO doesn't support that.
To make the method mockable we will have to use a DI(dependency injection) based code pattern.
**We can mock only those methods which are injectable**.
We have two options to introduce dependency injection in this code.
Use Delegation Design pattern with the help of interface
Introduce Monkey patching using the function as a type
Delegation using interface:
type Deligation interface {
Validate(num int) error
}
type DemoStruct struct {
delegate Deligation
}
func (DemoStruct) Validate(num int) error {
if num > 100 {
return fmt.Errorf("INVALID NUM %v", num)
}
return nil
}
func (l DemoStruct) Inc(num int) (int, error) {
err := l.delegate.Validate(num) // Call method using delegate
if err != nil {
return 0, err
}
num = num + 100
return num, nil
}
func main() {
s, err := DemoStruct{delegate: DemoStruct{}}.Inc(10) // assign delegate inside DemoStruct
if err != nil {
fmt.Println(err)
}
fmt.Println(s)
}
Using Monkey patching:
func Validate(num int) error {
if num > 100 {
return fmt.Errorf("INVALID NUM %v", num)
}
return nil
}
type DemoStruct struct {
Validate func(num int) error // function as a type
}
func (l DemoStruct) Inc(num int) (int, error) {
err := l.Validate(num)// It can be replaced in test cases.
if err != nil {
return 0, err
}
num = num + 100
return num, nil
}
func main() {
s, err := DemoStruct{Validate: Validate}.Inc(10) // assign Validate inside DemoStruct
if err != nil {
fmt.Println(err)
}
fmt.Println(s)
}
Ref: https://blog.myhro.info/2018/06/how-to-mock-golang-methods
Related
How can I compose the default Go HTTP file server (serve if exists, show file listing otherwise) with additional HTML?
Sample http.go with default file server:
package main
import "net/http"
func main() {
http.Handle("/", http.FileServer(http.Dir(".")))
http.ListenAndServe(":8090", nil)
}
Loading the default page (http://localhost:8090) gives something like:
<pre>LICENSE
README.md
studio.jpg
</pre>
I found it is declared at fs.go.
I want to keep that section, but with my own header and footer (preferably without copying the dirList function and making small changes):
<title>My files</title>
<pre>LICENSE
README.md
studio.jpg
</pre>
<p>And that's all, folks!</p>
Based on this answer, you can implement own FileSystem for a FileServer
This implementation is very buggy at best, and you should probably never ever use it, but it should show you how the FileSystem interface can be implemented for arbitrary 'files'.
type InMemoryFS map[string]http.File
type InMemoryFile struct {
at int64
Name string
data []byte
fs InMemoryFS
}
func NewFile(name string, data []byte) *InMemoryFile {
return &InMemoryFile{at: 0,
Name: name,
data: data,
fs: make(InMemoryFS)}
}
// Implements the http.File interface
func (f *InMemoryFile) Close() error {
return nil
}
func (f *InMemoryFile) Stat() (os.FileInfo, error) {
return &InMemoryFileInfo{f}, nil
}
func (f *InMemoryFile) Readdir(count int) ([]os.FileInfo, error) {
return nil, nil
}
func (f *InMemoryFile) Read(b []byte) (int, error) {
i := 0
for f.at < int64(len(f.data)) && i < len(b) {
b[i] = f.data[f.at]
i++
f.at++
}
return i, nil
}
func (f *InMemoryFile) Seek(offset int64, whence int) (int64, error) {
switch whence {
case 0:
f.at = offset
case 1:
f.at += offset
case 2:
f.at = int64(len(f.data)) + offset
}
return f.at, nil
}
type InMemoryFileInfo struct {
file *InMemoryFile
}
// Implements os.FileInfo
func (s *InMemoryFileInfo) Name() string { return s.file.Name }
func (s *InMemoryFileInfo) Size() int64 { return int64(len(s.file.data)) }
func (s *InMemoryFileInfo) Mode() os.FileMode { return os.ModeTemporary }
func (s *InMemoryFileInfo) ModTime() time.Time { return time.Time{} }
func (s *InMemoryFileInfo) IsDir() bool { return false }
func (s *InMemoryFileInfo) Sys() interface{} { return nil }
// CustomFsDecorator: is `http.FileSystem` decorator
type CustomFsDecorator struct {
http.FileSystem
}
func (fs CustomFsDecorator) Open(name string) (http.File, error) {
file, err := fs.FileSystem.Open(name)
if err != nil {
return nil, err
}
info, err := file.Stat()
if err != nil {
return nil, err
}
if info.IsDir() {
return file, nil
}
b, err := io.ReadAll(file)
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
// add header's lines
_, err = buf.Write([]byte("<title>My files</title>\n"))
if err != nil {
return nil, err
}
_, err = buf.Write(b)
if err != nil {
return nil, err
}
// add footer's lines
_, err = buf.Write([]byte("\n<p>And that's all, folks!</p>"))
if err != nil {
return nil, err
}
return NewFile(info.Name(), buf.Bytes()), nil
}
func Test(t *testing.T) {
cfsys := CustomFsDecorator{FileSystem: http.Dir("./static")}
fsys := http.FileServer(cfsys)
req := httptest.NewRequest(http.MethodGet, "/some.html", nil)
w := httptest.NewRecorder()
fsys.ServeHTTP(w, req)
res := w.Result()
defer func() {
_ = res.Body.Close()
}()
data, err := io.ReadAll(res.Body)
if err != nil {
t.Errorf("expected error to be nil got %v", err)
}
fmt.Println(string(data))
}
👇🏻
<title>My files</title>
<pre>LICENSE
README.md
studio.jpg
</pre>
<p>And that's all, folks!</p>
PLAYGROUND
I am wrapping errors (to add context) and am afterwards distinguishing between two errors. This is a scenario that I am currently using for tests. (Did the function recognise the error correctly?) My question is how I can reduce the verbosity.
I have two functions that create different errors:
func a() error {
return errors.New("a")
}
func b() error {
return errors.New("b")
}
They are both called by a third function that propagates the erorr.
func doStuff() error {
err := a()
if err != nil {
return WrapA{err}
}
err = b()
if err != nil {
return WrapB{err}
}
return nil
}
In my main function, I distinguish between both errors.
func main() {
fmt.Println("Hello, playground")
err := doStuff()
switch err.(type) {
case WrapA:
fmt.Println("error from doing a")
case WrapB:
fmt.Println("error from doing b")
case nil:
fmt.Println("nil")
default:
fmt.Println("unknown")
}
}
So far, so good. Unfortunately, to implement WrapA and WrapB, I need a lot of code:
type WrapA struct {
wrappedError error
}
func (e WrapA) Error() string {
return e.wrappedError.Error()
}
func (e WrapA) Unwrap() error {
return e.wrappedError
}
type WrapB struct {
wrappedError error
}
func (e WrapB) Error() string {
return e.wrappedError.Error()
}
func (e WrapB) Unwrap() error {
return e.wrappedError
}
In other languages, I would create a single Wrap struct and let WrapA and WrapB inherit from Wrap. But I don't see a way to do this in Go.
Any ideas on how to reduce the clutter?
Go Playground https://play.golang.org/p/ApzHC_miNyV
EDIT:
After seeing jub0bs answer, I want to clarify:
Both a() and b() are callbacks I have no control over. They may return various errors. This is the reason why I wrap them.
If I understand the problem correctly, you can indeed simplify things:
Define a and b as package-level error variables for ease and better performance.
Unless you require programmatic access to values only accessible in the context of the error that you're wrapping, you most likely don't need to declare those custom WrapA and WrapB error types. Instead, you can simply use the %w verb in conjunction with fmt.Errorf to produce a new error value that wraps the lower-level error.
You can then use errors.Is within a tagless switch to inspect the cause of the higher-level error returned by your doStuff function.
(Playground)
package main
import (
"errors"
"fmt"
)
var (
a = errors.New("a")
b = errors.New("b")
)
func doStuff() error {
err := a
if err != nil {
return fmt.Errorf("%w", err)
}
err = b
if err != nil {
return fmt.Errorf("%w", err)
}
return nil
}
func main() {
fmt.Println("Hello, playground")
switch err := doStuff(); {
case errors.Is(err, a):
fmt.Println("error from doing a")
case errors.Is(err, b):
fmt.Println("error from doing b")
case err == nil:
fmt.Println("nil")
default:
fmt.Println("unknown")
}
}
Adding a structured error version which composes a type Wrap along various more specific error types;
package main
import (
"errors"
"fmt"
)
func a() error {
return errors.New("something more specific broke in a")
}
func b() error {
return errors.New("something more specific broke in b")
}
func doStuff() error {
err := a()
if err != nil {
return ErrA{
Wrap: Wrap{err: err},
SpecficProp: "whatever",
}
}
err = b()
if err != nil {
return ErrB{
Wrap: Wrap{err: err},
SpecficProp2: "whatever else",
}
}
return nil
}
func main() {
fmt.Println("Hello, playground")
err := doStuff()
if target := (ErrA{}); errors.As(err, &target) {
fmt.Printf("%v\n", target)
} else if target := (ErrB{}); errors.As(err, &target) {
fmt.Printf("%v\n", target)
} else if err != nil {
fmt.Println("unknown")
} else {
fmt.Println("nil")
}
}
type Wrap struct {
err error
}
func (e Wrap) Error() string {
return e.err.Error()
}
func (e Wrap) Unwrap() error {
return e.err
}
type ErrA struct {
Wrap
SpecficProp interface{}
}
func (e ErrA) Error() string {
return fmt.Sprintf("got error of kind A with %#v, plus %T", e.SpecficProp, e.Unwrap())
}
type ErrB struct {
Wrap
SpecficProp2 interface{}
}
func (e ErrB) Error() string {
return fmt.Sprintf("got error of kind B with %#v, plus %T", e.SpecficProp2, e.Unwrap())
}
Use constant errors if you can. Then you could switch on the error itself.
I have spent some time reading the code and docs of go-yaml, but I have not found any way to do this, except forking the project..
I want to extend the YAML unmarshaller so that it can accept a custom YAML tag (!include <file> in this case), which in turn would allow me to add support for including files. This is easily implemented with other YAML libraries, like in this answer.
Is there any way to accomplish this, using the public interface of the library (or another yaml library)?
Yes, this is possible (since v3). You can load the whole YAML file into a yaml.Node and then walk over the structure. The trick is that yaml.Node is an intermediate representation which you can only access if you define an unmarshaler.
For example:
package main
import (
"errors"
"fmt"
"io/ioutil"
"gopkg.in/yaml.v3"
)
// used for loading included files
type Fragment struct {
content *yaml.Node
}
func (f *Fragment) UnmarshalYAML(value *yaml.Node) error {
var err error
// process includes in fragments
f.content, err = resolveIncludes(value)
return err
}
type IncludeProcessor struct {
target interface{}
}
func (i *IncludeProcessor) UnmarshalYAML(value *yaml.Node) error {
resolved, err := resolveIncludes(value)
if err != nil {
return err
}
return resolved.Decode(i.target)
}
func resolveIncludes(node *yaml.Node) (*yaml.Node, error) {
if node.Tag == "!include" {
if node.Kind != yaml.ScalarNode {
return nil, errors.New("!include on a non-scalar node")
}
file, err := ioutil.ReadFile(node.Value)
if err != nil {
return nil, err
}
var f Fragment
err = yaml.Unmarshal(file, &f)
return f.content, err
}
if node.Kind == yaml.SequenceNode || node.Kind == yaml.MappingNode {
var err error
for i := range node.Content {
node.Content[i], err = resolveIncludes(node.Content[i])
if err != nil {
return nil, err
}
}
}
return node, nil
}
type MyStructure struct {
// this structure holds the values you want to load after processing
// includes, e.g.
Num int
}
func main() {
var s MyStructure
yaml.Unmarshal([]byte("!include foo.yaml"), &IncludeProcessor{&s})
fmt.Printf("Num: %v", s.Num)
}
Code prints Num: 42 when a file foo.yaml exists with the content num: 42.
Modified #flyx's original code a little to make it modular for adding custom resolvers.
package main
import (
"errors"
"fmt"
"io/ioutil"
"os"
"gopkg.in/yaml.v3"
)
var tagResolvers = make(map[string]func(*yaml.Node) (*yaml.Node, error))
type Fragment struct {
content *yaml.Node
}
func (f *Fragment) UnmarshalYAML(value *yaml.Node) error {
var err error
// process includes in fragments
f.content, err = resolveTags(value)
return err
}
type CustomTagProcessor struct {
target interface{}
}
func (i *CustomTagProcessor) UnmarshalYAML(value *yaml.Node) error {
resolved, err := resolveTags(value)
if err != nil {
return err
}
return resolved.Decode(i.target)
}
func resolveTags(node *yaml.Node) (*yaml.Node, error) {
for tag, fn := range tagResolvers {
if node.Tag == tag {
return fn(node)
}
}
if node.Kind == yaml.SequenceNode || node.Kind == yaml.MappingNode {
var err error
for i := range node.Content {
node.Content[i], err = resolveTags(node.Content[i])
if err != nil {
return nil, err
}
}
}
return node, nil
}
func resolveIncludes(node *yaml.Node) (*yaml.Node, error) {
if node.Kind != yaml.ScalarNode {
return nil, errors.New("!include on a non-scalar node")
}
file, err := ioutil.ReadFile(node.Value)
if err != nil {
return nil, err
}
var f Fragment
err = yaml.Unmarshal(file, &f)
return f.content, err
}
func resolveGetValueFromEnv(node *yaml.Node) (*yaml.Node, error) {
if node.Kind != yaml.ScalarNode {
return nil, errors.New("!getValueFromEnv on a non-scalar node")
}
value := os.Getenv(node.Value)
if value == "" {
return nil, fmt.Errorf("environment variable %v not set", node.Value)
}
var f Fragment
err := yaml.Unmarshal([]byte(value), &f)
return f.content, err
}
func AddResolvers(tag string, fn func(*yaml.Node) (*yaml.Node, error)) {
tagResolvers[tag] = fn
}
func main() {
// Register custom tag resolvers
AddResolvers("!include", resolveIncludes)
AddResolvers("!getValueFromEnv", resolveGetValueFromEnv)
type MyStructure struct {
// this structure holds the values you want to load after processing
// includes, e.g.
Num int
}
var s MyStructure
os.Setenv("FOO", `{"num": 42}`)
err := yaml.Unmarshal([]byte("!getValueFromEnv FOO"), &CustomTagProcessor{&s})
if err != nil {
panic("Error encountered during unmarshalling")
}
fmt.Printf("\nNum: %v", s.Num)
err = yaml.Unmarshal([]byte("!include foo.yaml"), &CustomTagProcessor{&s})
if err != nil {
panic("Error encountered during unmarshalling")
}
fmt.Printf("\nNum: %v", s.Num)
}
I want to build this:
finalResult, err := Function1(whatever type)
.Function2(whatever type)
.Function3(whatever type)
Something similar to promises in javascript but not necessarily the same concepts. Or similar to nested methods in Java. I just pretend avoid more code for the same tasks.
I don't want to do this :
result, err := new(Function1(whatever type)) //or *Function1(whatever type)
if err != nil {...}
result1, err := result.Function2(whatever type)
if err != nil {...}
finalResult, err := result1.Function3(whatever type)
if err != nil {...}
I've been trying with several options with structs and interfaces but I can't get any result.
My apology if I have a mistake in my grammar. I'm not still so good with my skill English.
Thanks,
David
I think you mean the Fluent API design pattern. You return the same Object, or struct in Go, over and over.
This pattern does not allow you to return a tuple, or multiple return types though. You can only return one object.
https://play.golang.org/p/9PceZwi1a3
package main
import (
"fmt"
)
type Object struct {
Value string
Error error
}
func (o *Object) Before(s string) *Object {
o.Value = s + o.Value
// add an error if you like
// o.Error = error.New(...)
return o
}
func (o *Object) After(s string) *Object {
// could check for errors too
if o.Error != nil {
o.Value = o.Value + s
}
return o
}
func main() {
x := Object{}
x.
Before("123").
After("456").
After("789").
Before("0")
if x.Error != nil {
// handle error
}
fmt.Println(x.Value)
}
Edit: sberry's answer had a good idea. Add an Error state on the Object struct itself which could allow u to check for errors in each func call.
Since you are new, please remember to evaluate all answers and mark the best one you believe lead you the answer.
The only way to do this would be to have each FunctionX be a method on a receiver (most likely a pointer receiver if you are mutating state) and have them each return the receiver. Like so
type someNumber struct {
n int32
}
func (s *someNumber) Add(i int32) *someNumber {
s.n += i
return s
}
func (s *someNumber) Multiply(i int32) *someNumber {
s.n *= i
return s
}
func (s *someNumber) Subtract(i int32) *someNumber {
s.n -= i
return s
}
func main() {
num := &someNumber{n: 0}
result := num.Add(5).Multiply(4).Subtract(10)
fmt.Println(result.n)
}
You could set and error on the someNumber as well, and check it at the end.
If you are looking to actually carry through the error, then you would need to do something like this.
func Function1(a int, err error) (int, error) {
if err != nil {
return a, err
}
return a, nil
}
func Function2(a int, err error) (int, error) {
if err != nil {
return a, err
}
return a*2, nil
}
func Function3(a int, err error) (int, error) {
if err != nil {
return a, err
}
return a*3, nil
}
func main() {
a, err := Function3(Function2(Function1(1, nil)))
fmt.Println(a, err)
}
But, it seems like you are looking for the type of behavior an Error Monad would bring and that does not exist in Go.
Run it at
https://play.golang.org/p/sl12vfS9vP
package main
import "fmt"
func main() {
err := run()
if err != nil {
fmt.Printf("%#v", err)
}
}
func run() (err error) {
return check()
}
func check() *Result {
return nil
}
type Result struct {
message string
}
func (result *Result) Error() string {
return result.message
}
This is discussed on the FAQ and the Go Traps website:
An interface value is nil only if the inner value and type are both unset, (nil, nil). In particular, a nil interface will always hold a nil type. If we store a pointer of type *int inside an interface value, the inner type will be *int regardless of the value of the pointer: (*int, nil). Such an interface value will therefore be non-nil even when the pointer inside is nil.
(...)
To return a proper nil error to the caller, the function must return an explicit nil:
func returnsError() error {
if bad() {
return ErrBad
}
return nil
}
Francesc Campoy Flores (from the Go team at Google) talked about this particular issue in his presentation at dotGo this year.
You can think an interface value has 2 parts; a type and a value. Therefore an interface of type *Result and value nil is not equal to an interface with both type and value nil.
You can fix your code by typing the nil in the comparison:
http://play.golang.org/p/E9kro7Fkbr
package main
import "fmt"
func main() {
err := run()
if err != (*Result)(nil) {
fmt.Printf("%#v", err)
}
}
func run() (err error) {
return check()
}
func check() *Result {
return nil
}
type Result struct {
message string
}
func (result *Result) Error() string {
return result.message
}
In a nutshell: don't mix interfaces and pointers/values when using direct or named return values in a function.
The goal is to create an error aggregator, e.g:
func checkStatus() *Result {
r := &Result{}
// ... do checks and append to r.message ...
if r.message == "" {
return nil
}
return r
}
func checkSomething() error {
return runDiagnostics()
}
func runDiagnostics() *Result {
... do something
// all ok
return nil
}
.. somewhere else .... (using named return values)
if err = checkStatus(); err != nil {
return
}
.. this fails even when runDiagnostics() return nil ...
if err = checkSomething(); err != nil {
... err is always "something"
}
detailed check with a pointer http://play.golang.org/p/WPGy_ooXmP
detailed check with an interface http://play.golang.org/p/JjWxEj9WRX
solution with an error indicator http://play.golang.org/p/C30s49GiIN
package main
import "fmt"
func main() {
err := run()
if err != nil {
fmt.Printf("%#v", err)
}
}
func run() (err error) {
_, err = check()
return
}
func check() (*Result, error) {
return nil, nil
}
type Result struct {
message string
}
func (result *Result) Error() string {
return result.message
}
solution with an interface http://play.golang.org/p/bFysxTFVIH
package main
import "fmt"
func main() {
err := run()
if err != nil {
fmt.Printf("%#v", err)
}
}
func run() (err error) {
return check() // <-- for direct return or named return value an "interface{}" must be used
}
// uses an interface - Result
func check() Result {
return nil
}
type Result interface {
Error() string
}
type result struct {
message string
}
func (result *result) Error() string {
return result.message
}