简体   繁体   English

Mocking 用于在 go 中进行测试的内部函数(或更深)

[英]Mocking a inner function(or even more deep) for testing in go

is there a way to achieve this?有没有办法做到这一点? I want to Mock the response of a function call from within another function call.我想从另一个 function 调用中模拟 function 调用的响应。 Example例子

main.go主要.go

type Crs struct {}
func (cr crs)TheFunction() error {
   // Some code
   _ := ToMockResponse(hello string)
   return nil
}

func ToMockResponse() error {
    return somerror
}

and in my test file在我的测试文件中

main_test.go main_test.go

func TestTheFunction(t *testing.T) {
    cr = Crs{}
    mockInstance = new(randomMock)
    mockInstance.On("ToMockResponse").Return(nil)

    err := cr.TheFunction()
    assert.NoError(t, err)
}

I'm not sure if what I did is correct.我不确定我做的是否正确。 What I'm trying to achieve is that I just want to have a Mock response of ToMockResponse whenever it's being called inside TheFunction我想要实现的是,只要在 TheFunction 中调用它,我只想对 ToMockResponse 进行模拟响应

I have seen and read most of the tutorial but all of them shows a Mock response from a method of a class. But there are no function-to-function mocking samples.我已经看过并阅读了大部分教程,但它们都显示了来自 class 方法的模拟响应。但是没有函数到函数 mocking 示例。 Hope you can provide a solution to this.希望您能为此提供解决方案。

Without getting into whether you should do this, and assuming that you have a valid reason to do so, one way to mock functions is to use them via a level of indirection.无需考虑您是否应该这样做,并假设您有充分的理由这样做,模拟函数的一种方法是通过间接级别使用它们。 You can then substitute a suitable alternative in your indirection for the purposes of testing.然后,您可以出于测试目的在您的间接寻址中替换一个合适的替代方案。

An interface is one way to achieve that, but GoLang supports functions as values, so another way is to use a simple variable of an appropriate function type:接口是实现这一点的一种方法,但 GoLang 支持函数作为值,因此另一种方法是使用适当的 function 类型的简单变量:

Adapted to your example, this might look similar to:适应你的例子,这可能看起来类似于:

var toMockResponse = ToMockResponse

func (cr crs)TheFunction() error {
   // Some code
   _ := toMockResponse(hello string)
   return nil
}

func ToMockResponse() error {
    return somerror
}

and your test:和你的测试:

func TestTheFunction(t *testing.T) {
    cr = Crs{}
    ofn := toMockResponse
    toMockResponse = func(string) error { return nil }
    defer func() { toMockResponse = ofn }()

    err := cr.TheFunction()
    assert.NoError(t, err)
}

I have assumed that you need to export the ToMockResponse ;我假设您需要导出ToMockResponse the function variable is deliberately not exported so that it cannot be manipulated outside of the package itself.故意导出 function 变量,以便不能在 package 本身之外对其进行操作。

If the function being redirected is itself not exported, denying the ability to use the case difference of exported vs non-exported symbols to differentiate them, then you may need to be a bit more creative with your naming.如果被重定向的 function本身没有导出,拒绝使用导出符号与未导出符号的大小写差异来区分它们的能力,那么您可能需要在命名时更有创意一些。 eg a variable called toMockResponseFn .例如,一个名为toMockResponseFn的变量。

Footnote脚注

ofn is mnemonic for "original function". ofn是“原始函数”的助记符。 In a more complicated test you can preserve the pattern by creating a scope for each ofn you need ( defer operates w.r.t the containing function, not the scope):在更复杂的测试中,您可以通过为您需要的每个创建一个ofn来保留模式( defer操作 w.r.t 包含 function,而不是范围):

   {
      ofn := toMockResponse
      toMockResponse = func(string) error { return nil }
      defer func() { toMockResponse = ofn }()
   }
   {
      ofn := now
      now = func() time.Time { return time.Date(..etc..) }
      defer func() { now = ofn }()
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM