草庐IT

unit-testing - 以 http 作为包装函数的依赖项的单元测试

coder 2024-07-09 原文

我有以下函数,在@poy 的帮助下,我能够为它创建模拟以便对其进行单元测试。

现在的问题是我有包装函数也需要测试

这是原始函数,已经过测试

func httpReq(cc []string, method string, url string) ([]byte, error) {
    httpClient := http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        return nil, errors.Wrap(err, "failed to execute http request")
    }
    //Here we are passing user and password
    req.SetBasicAuth(cc[1], cc[2])
    res, err := httpClient.Do(req)
    if err != nil {
        fmt.error(err)
    }
    val, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.error(err)
    }
    defer res.Body.Close()
    return val, nil
}

这是按预期工作的测试,此测试使用 https://golang.org/pkg/net/http/httptest/为了模拟 http 请求。

func Test_httpReq(t *testing.T){

  expectedValue = "some-value"
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){

    u,p,ok := r.BasicAuth()
    if !ok || u != "fakeuser" || p != "fakepassword" {
      t.Fatal("wrong auth")
    }
    w.Write([]byte(expectedValue))
  })

  val, err := httpReq(
   []string{"fakeuser", "fakepassword"}, 
   http.MethodPost, 
   server.URL,
  )

  if err != nil{
    t.Fatal(err)
  }

  if val != expectedValue {
    t.Fatalf("expected %q to equal %q", val, expectedValue)
  }

现在的问题是我还有另一个函数调用上述函数也需要测试。

这是使用 httpReq 的函数,我还需要为它创建测试

func (c *Service) invoke(Connection Connection, args []string) {
    service, err := c.getService(Connection, args)

    serviceC, err := c.getServiceK(service, []string{"url", “user”, “id”})
    c := strings.Fields(serviceC)
        //—————Here we are using the http function again 
    val, err := httpReq(c[1], c[1],”post”, c[0])
    if err != nil {
        fmt.println(err)
    }
    fmt.Print(string(val))
}

现在,当我对其进行测试时,我在 http 请求方法 中遇到了错误,因为在这里我无法模拟 http。

Golang 有什么技术可以帮助解决这种情况吗? 我已经搜索过了,比如依赖注入(inject),发现也许接口(interface)可以提供帮助,但由于这是 http,我不确定该怎么做。

任何具有这种背景的例子都会对我很有帮助。

最佳答案

服务对象可以有这样的接口(interface)

type Service struct {
    serviceK typeK
    serviceHttp serviceHttp // of type interface hence can be mocked
}

普通应用程序代码可以使用实际对象初始化服务。测试将有模拟对象

type Req struct {
}

type Resp struct {
}

type ServiceHttp interface{
    HttpReq(params Req)(Resp, error)
}

type Implementation struct {
}

func (i *Implementation)HttpReq(params Req)(Resp, error){
   // buid http request
}

func (c *Service) invoke(Connection Connection, args []string) {

    service, err := c.getService(Connection, args)

    serviceC, err := c.getServiceK(service, []string{"url", “user”, “id”})
    c := strings.Fields(serviceC)

    serviceImp := c.GetServiceImp()

    // init params with the required fields
    val, err := c.HttpReq(params)
    if err != nil {
      fmt.println(err)
    }
    fmt.Print(string(val))

}

当您运行测试时,您可以使用返回虚拟响应的模拟实现来初始化服务对象。

type MockImplementation struct {
}

func (i *MockImplementation)HttpReq(Resp, error){
    // return mock response
}

func TestMain(){
  services := {
     serviceHttp:MockImplementation{},
     serviceK: typeK{}, // initialise this
  }
}

这是测试它的方法之一。其他方式可能是我猜 httpReq 返回 http.ResponseWriter 的地方,你可以使用 httptest.ResponseRecorder 来测试它。

关于unit-testing - 以 http 作为包装函数的依赖项的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53801576/

有关unit-testing - 以 http 作为包装函数的依赖项的单元测试的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  6. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  7. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  8. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  9. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  10. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

随机推荐