Golang:在调用Init方法之前模拟一个接口方法。

huangapple go评论79阅读模式
英文:

Golang: Mock an interface method before Init method is called

问题

如何模拟在包的init()方法中调用的内容?

例如:

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")
}

问题是在服务被模拟替换之前,init()方法就已经被调用了。

英文:

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.

答案1

得分: 1

这是一个涉及可变全局状态的问题。

我的建议是添加一个标志,以便在特定条件下不运行此代码,或者公开一个私有函数,可以在内部测试中恢复/更新此全局变量。

这反映了你的设计:如果测试很复杂,也许你应该进行重构。

创建一个名为Application的对象,其中包含一个字段Service,在构造函数/构建器/工厂中创建将更容易进行测试。

init的使用非常微妙。除了将驱动程序注册到sql包中,我从来没有使用过它(也许用于处理标志)。

也许你可以在你的设计中添加更多面向对象的特性。

英文:

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

答案2

得分: 0

你需要在init()函数内部调用otherMethod()。否则,在init()之前不能调用它。

英文:

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

答案3

得分: 0

我找到了一个解决方法,你可以通过以下方式阻止初始化代码在测试中被执行,并独立测试该方法:

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()
  }
}

这样可以防止初始化服务调用被执行。

英文:

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.

huangapple
  • 本文由 发表于 2022年3月22日 12:34:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/71566952.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定