【问题标题】:How to mock or stub an external request, not necessarily an http one?如何模拟或存根外部请求,不一定是 http 请求?
【发布时间】:2020-12-25 10:54:20
【问题描述】:

我想模拟或存根外部请求。这不是一个简单的 HTTP 请求,也没有对底层库的直接访问,也没有关于它是如何实现的信息,因此它应该被视为一些外部请求,可以是 http、文件、数据库。简化代码如下:

def my_external_call
  Lib1::get_some_data()
end

我知道 my_external_call() 可以返回什么。如何模拟或存根?

【问题讨论】:

  • my_external_call 是在类上定义的方法,还是只是在顶层?如果它是在一个类上定义的,你只需说expect(my_class).to receive(:my_external_call).and_return(some_stubbed_result)
  • @maxpleaner 在类或模块中。请在下面查看我的 cmets

标签: ruby testing rspec


【解决方案1】:

我会这样做:

describe "method that uses external service" do
  before do 
    allow(Lib1).to_receive(:get_some_data).and_return(
      { example: "response" }      # or whatever is returned from the external service
    )
  end

  it "works" do
    # your test for the method that triggers the external call
  end
end

【讨论】:

  • 好的,但实际测试的是什么?它不会测试响应本身,它的内容,而只会在Lib1 中测试get_some_data()存在?如果是这样,有没有办法让它更有用?
  • 或者首先,该测试是否会发出实际外部请求?如果是一个实际的请求,它在什么意义上是在嘲笑?有什么比简单地调用my_external_call() 更好?
  • 此示例不会测试Lib1.get_some_data 的响应,恕我直言,这根本没有任何意义。您不想测试返回存根数据的方法,因为这样您就不会测试方法本身,而只会测试存根数据。通过这样的测试,您可以测试任何其他依赖于Lib1.get_some_data 的方法。如果Lib1.get_some_data 返回了预期的响应,它基本上测试了依赖方法是否有效。当您想测试 Lib1.get_some_data 方法本身时,您不能存根该方法,但需要存根该库中的更多低级方法。
  • 当使用allow(object).to_receive(:method_name).and_return(response) 时,该方法的原始实现将不再被调用。因此,该方法内的外部调用不会发生。我不会在我的测试中运行外部调用。
【解决方案2】:

另外,请阅读 Martin Fowler 的这篇非常著名的文章:Mocks aren't Stubs,这样您就可以很好地了解 mock 和 stub。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多