使用 RSPec 模拟/存根系统调用 [英] Mocking/stubbing system call using 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屋!