简体   繁体   English

Go 中的条件 Mocking

[英]Conditional Mocking in Go

I want to mock Rest API calls in GoLang based on certain condition.我想根据特定条件在 GoLang 中模拟 Rest API 调用。 For example, i have a method defined like below:例如,我有一个定义如下的方法:

func Method() {
  resp1, err := DoSomething1()
  resp2, err := DoSomething2()
}

func DoSomething1() (*http.Response, error) {
  return Get(url string)
}

func DoSomething2() (*http.Response, error) {
  return Get(url string)
}

Now, i want to define my mock response for each get calls separately.现在,我想分别为每个 get 调用定义我的模拟响应。 ie when i call DoSomething1() from Method(), i want to mock the get call and return response R1 and when i call DoSomething2() from Method(), i want to mock the get call and return response R2.即,当我从 Method() 调用 DoSomething1() 时,我想模拟 get 调用并返回响应 R1,而当我从 Method() 调用 DoSomething2() 时,我想模拟 get 调用并返回响应 R2。

So far, i have been able to mock a single get call that would return same response for any request by defining Get as an interface and mocking it, however i am trying to define responses for each of these calls.到目前为止,我已经能够通过将 Get 定义为接口并将其定义为 mocking 来模拟单个 get 调用,该调用将为任何请求返回相同的响应,但是我正在尝试为这些调用中的每一个定义响应。

Below is the mock interface that i have defined that i am using to mock get/post calls:下面是我定义的用于模拟 get/post 调用的模拟接口:

package clientMock

import (
    "net/http"
)

type MockClient struct {
}

var (
    GetMock  func(url string, queryParams map[string]interface{}, headerParams map[string]interface{}) (*http.Response, error)
    PostMock func(url string, reqBody interface{}, queryParams map[string]interface{}, headerParams map[string]interface{}) (*http.Response, error)
)

func (m MockClient) Get(url string, queryParams map[string]interface{}, headerParams map[string]interface{}) (*http.Response, error) {
    return GetMock(url, queryParams, headerParams)
}

func (m MockClient) Post(url string, reqBody interface{}, queryParams map[string]interface{}, headerParams map[string]interface{}) (*http.Response, error) {
    return PostMock(url, reqBody, queryParams, headerParams)
}

Below is the sample Test Class that i have defined for testing Method, however unable to figure out how can i change the mock response when DoSomething2() is being called from Method():下面是我为测试方法定义的示例测试 Class,但是无法弄清楚当从 Method() 调用 DoSomething2() 时如何更改模拟响应:

func TestHandleSuccess(t *testing.T) {

    resBody := `{"instance_url":"instance_url","access_token":"access_token"}`
    r := ioutil.NopCloser(bytes.NewReader([]byte(resBody)))
    clientMock.GetMock = func(url string, queryParams, headerParams map[string]interface{}) (*http.Response, error) {
        return &http.Response{
            StatusCode: 200,
            Body:       r,
        }, nil

    }

    err := method.Method()
    assert.Nil(t, err)
}

Given the code you've provided, I'm guessing the parameter url passed into Get from your "do something" functions is different (otherwise I'm not sure why you'd need the behavior to change).鉴于您提供的代码,我猜从您的“做某事”函数传递给Get的参数url是不同的(否则我不确定您为什么需要改变行为)。 If this is the case, you could add a condition in your mock to change behavior based on the url .如果是这种情况,您可以在模拟中添加一个条件以更改基于url的行为。

clientMock.GetMock = func(url string, queryParams, headerParams map[string]interface{}) (*http.Response, error) {
    var resBody string
    if url == "/call1" {
        resBody = `{"instance_url":"instance_url","access_token":"access_token"}`
    } else if url == "/call2" {
        resBody = `{"something":"else"}`
    }
    return &http.Response{
        StatusCode: 200,
        Body:       ioutil.NopCloser(bytes.NewReader([]byte(resBody))),
    }, nil
}

This is how you should think about your code - behavior shouldn't change based on where a call is coming from.这就是你应该如何看待你的代码——行为不应该根据调用的来源而改变。 Instead, it should change based on the inputs to the function being called.相反,它应该根据被调用的 function 的输入而改变。 This decouples your function from its caller and makes reuse and refactoring easier.这将您的 function 与其调用者分离,并使重用和重构更容易。

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

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