【问题标题】:Mocking/stubbing system call using RSPec使用 RSPec 模拟/存根系统调用
【发布时间】:2014-07-01 15:10:44
【问题描述】:

这是帮助模块:

module SendingMailHelper
  def send_mail(subject, body)
    to_email_id = " abc@gmail.com"
    cc_email_id = "def@gmail.com"
    html_message = %{<html><body>#{body}</body></html>}
    flag=false
    while(!flag) do
      flag = system %{echo "#{html_message}" | mutt -e "set content_type=text/html" -s "#{subject}" #{cc_email_id} -- #{to_email_id}}
    end
    flag
  end
end

我编写规范的方式如下,但它不起作用:

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe SendingMailHelper do
  it "test something" do
    html_message = %{<html><body>www.google.com</body></html>}
    to_email_id = " abc@gmail.com"
    cc_email_id = "def@gmail.com"
    subject = "test e-mail"
    SendingMailHelper.expects(:system).with(%{echo "#{html_message}" | mutt -e "set content_type=text/html" -s "#{subject}" #{cc_email_id} -- #{to_email_id}}).returns(true).once
    helper.send_mail("test e-mail","www.google.com").should==true
  end
end

得到以下错误:

SendingMailHelper test something
     Failure/Error: SendingMailHelper.expects(:system).with(%{echo "#{html_message}" | mutt -e "set content_type=text/html" -s "#{subject}" #{cc_email_id} -- #{to_email_id}}).returns(true).once
     Mocha::ExpectationError:
       not all expectations were satisfied
       unsatisfied expectations:
       - expected exactly once, not yet invoked:

我还想以这样一种方式模拟它,模拟 mutt 两次返回 false 并在第三次调用中返回 true 以测试重试机制。有没有办法做到这一点?

【问题讨论】:

  • 试试Kernel.expects(:system)...
  • 我应该如何修复上述测试用例?

标签: ruby-on-rails ruby rspec


【解决方案1】:
require_relative './sending_mail_helper'
require 'rspec/mocks/standalone'

describe SendingMailHelper do
  let(:helper) do
    Class.new do
      include SendingMailHelper
      attr_reader :system_calls

      def system(*args)
        @system_calls ||= []
        @system_calls << args
        [false, false, true][(@system_calls.size - 1) % 3]
      end
    end.new
  end

  it "test the call is made" do
    html_message = %{<html><body>www.google.com</body></html>}
    to_email_id = " abc@gmail.com"
    cc_email_id = "def@gmail.com"
    subject = "test e-mail"
    helper.send_mail("test e-mail","www.google.com")
    # check it was called once
    helper.system_calls.size should eq 1
    # check it was called with appropriete arguments
    helper.system_calls.last.first.should eq %{echo "#{html_message}" | mutt -e "set content_type=text/html" -s "#{subject}" #{cc_email_id} -- #{to_email_id}}
  end

  it "retries the command until it succeded" do
    helper.send_mail("test e-mail","www.google.com")
    helper.system_calls.size.should eq 3
  end
end

您可以使用这个小技巧。实际上,这几乎就是 stub 和 mocks 用来监控函数调用的方式。尝试使用 rspec-mock 工具运行测试失败了。我个人建议你不要测试系统调用,它实际上会在你的测试中带来很多耦合和实现并使代码更难维护。我给你的另一个建议是使用一些 ruby​​ gem 来处理你试图实现的电子邮件功能,使用 sys 调用命令。最后很抱歉使用shoulds,但我在我的计算机上有旧的 rspec gem 并且缺少新的 expect 语法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多