0

e.g

type test struct { // few fields}
func (t *test) createresource(res1 string,res2 string)error {
     //doing some task

     t.createsubresource(res1)
}

func (t *test)createsubresource(res1 string)error{
    //perform some task
}

I want to write test function for createresource , how can I mock t.createsubresource(res1) call. This is legacy code and I don't have permission to modify any above function.

  • 2
    You cannot. Stop that mocking business, it doesn't work well in Go. If you need a special test double for createsubresource than you will have to modify test to accomodate for switching that (e.g. via an interface). – Volker Nov 23 '21 at 08:50
  • Can you please provide example ? – Nilesh Salunkhe Nov 23 '21 at 08:53
  • E.g. as a field in the test struct: `type test struct {... csr func(res1 string) ...}` which points to the real implementation and can be switched to an appropriate test double if needed. – Volker Nov 23 '21 at 09:17
  • Got it ,In my case I don't have provision to change the existing code block. – Nilesh Salunkhe Nov 23 '21 at 09:35

1 Answers1

6

Your mock can be done using interfaces, as for example:

main.go

package main

type TestInterface interface {
    CreateResource(res1 string, res2 string) error
    CreateSubresource (res1 string) error
}

func main() {
    DoSomething(new(Test))   
}

func DoSomething(t TestInterface) {
    t.CreateResource()
}

main_test.go

package main

import "testing"

type TestMock struct {}

func (tm *TestMock) CreateResource(res1 string, res2 string) error {
    return nil
}

func (tm *TestMock) CreateSubresource(res1 string) error {
    return nil
}

func TestDoSomething(t *testing.T) {
    err := DoSomething(new(TestMock))
    //... do your assertions
}

Why does it works like that?

Calling a function that depends on a specific structure does not allow you to inject alternatives to it, that's why a solution using interface needs to be created. By having an interface, just implement a new structure that matches that interface and pass it as a dependency injection to the procedure that will be tested.

Also, check this out:

  • There is no easy way, by default, to just point your original structure and tell Go to make a mock from it. Maybe some 3rd party lib can do it (but I didn't saw that yet).
  • In go, public and private declarations are defined by the first letter as uppercase. By the lower cases declarations in your sample I've noticed that everything is private.
  • Usually it is not a good practice to test private methods. There are a lot of discussions about this topic, you can take a look in this one here
  • There are also some support libs to make assertions and mocks like for example stretchr/testify, please make a research first.

I hope that it helps you.

Marcel Kohls
  • 1,650
  • 16
  • 24