如何在Go语言中模拟内部方法

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

How to Mock inner methods in GoLang

问题

你好!以下是翻译好的内容:

type test struct { // 几个字段 }
func (t *test) createresource(res1 string, res2 string) error {
    // 执行一些任务

    t.createsubresource(res1)
}

func (t *test) createsubresource(res1 string) error {
    // 执行一些任务
}

我想为createresource编写测试函数,如何模拟 t.createsubresource(res1)的调用?这是旧代码,我没有权限修改上面的任何函数。

英文:

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.

答案1

得分: 5

你可以使用接口来模拟,例如:

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
}

为什么要这样做?

调用依赖于特定结构的函数不允许您注入替代品,因此需要创建一个使用接口的解决方案。通过拥有一个接口,只需实现一个与该接口匹配的新结构,并将其作为依赖注入传递给将被测试的过程。

另外,请查看以下内容:

  • 默认情况下,没有简单的方法可以指向您的原始结构并告诉Go从中创建一个模拟。也许有一些第三方库可以做到这一点(但我还没有看到)。
  • 在Go中,公共和私有声明由首字母大写来定义。通过您示例中的小写声明,我注意到所有内容都是私有的。
  • 通常不建议测试私有方法。关于这个话题有很多讨论,你可以看看这个
  • 还有一些支持断言和模拟的库,例如stretchr/testify,请先进行一些研究。

希望对你有所帮助。

英文:

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.

huangapple
  • 本文由 发表于 2021年11月23日 16:46:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/70077808.html
匿名

发表评论

匿名网友

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

确定