cosbor11
cosbor11

Reputation: 16024

Golang: Mock an interface method before Init method is called

How can I mock something that gets called in a package init() method?

For example:

main.go


var myService MyService = myservicepkg.New()

func init(){
   response := myService.get()
}

func otherMethod(){
   //do something
}

maintest.go

func Test_otherMethod(){
  ctrl := NewController(t)
  defer ctrl.Finish()
  myServiceMock = myservicepkg.NewMock(myService)

  myServiceMock.EXPECT().get().return("success")
}

The problem is that init() is called before the service is replaced by the mock.

Upvotes: 0

Views: 1139

Answers (3)

cosbor11
cosbor11

Reputation: 16024

I found a workaround, you can prevent the init code from being executed in your test and test the method in isolation like this:

func init(){
  if len(os.Args) > 0 && strings.HasSuffix(os.Args[0], ".test") {
    log.Printf("skipping jwt.init() for testing")
  } else if len(os.Args) > 1 && strings.HasSuffix(os.Args[1], "-test.run") {
    log.Printf("skipping jwt.init() for testing")
  } else { 
    response := myService.get()
  }
}

This will prevent the init service calls from being called.

Upvotes: 0

Tiago Peczenyj
Tiago Peczenyj

Reputation: 4623

This is the issue of work with a mutable global state.

My advice is to add a flag to not run this on certain conditions or expose a private function that can recover/update this global variable in an internal test.

This reflects your design: if it is complicate to test, perhaps you should refactor.

Create an object Application with a field Service, created on the constructor/builder/factory will be easier to test.

The usage of init is very delicate. Besides register a driver into sql packages, I never use it (perhaps to handle flags).

Perhaps you can add more OO to your design

Upvotes: 1

Faizan Khalid
Faizan Khalid

Reputation: 135

You will need to call the otherMethod() inside init(). It can't be called before init() otherwise.

Upvotes: 0

Related Questions