使用 RSPec 模拟/存根系统调用 [英] Mocking/stubbing system call using RSPec

查看:56
本文介绍了使用 RSPec 模拟/存根系统调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是辅助模块:

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

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

The way I have written my spec is as follows, but it is not working:

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 以测试重试机制.有没有办法做到这一点?

I also want to mock it in such a way that mocked mutt returns false twice and true in the third call to test the retry mechanism. Is there a way to do that?

推荐答案

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

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

You could use this little hack. Actually this is pretty much what stub and mocks do to monitor function calls.Trying to run the tests using the rspec-mock facilities failed badly.Personally I would advise you not to test the system calls it actually brings a lot of coupling in your tests and implemetation and makes the code harder to maintain.Another advise i would give you is using some ruby gem to handle the email functionalities you are trying to achieve insted of using sys calls to commands.Finally sorry for the use of shoulds but i have old rspec gem on my computer and the new expect syntax is missing.

这篇关于使用 RSPec 模拟/存根系统调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆