RSpec::Mocks
来源:互联网 发布:淘宝开特产店证件 编辑:程序博客网 时间:2024/05/29 12:29
Test Doubles, Method Stubs, Message Expectations
123
thingamajig_double = double('thing-a-ma-jig')stub_thingamajig = stub('thing-a-ma-jig')mock_thingamajig = mock('thing-a-ma-jig')
double()
,stub()
,mock()
都会返回一个RSpec::Mocks::Mock
的实例
可以在这个实例上生成method stubs和message expectations
12345678910111213
describe Statement do it "logs a message on generate()" do customer = stub('customer') customer.stub(:name).and_return('Aslak') logger = mock('logger') statement = Statement.new(customer, logger) logger.should_receive(:log).with(/Statement generated for Aslak/) statement.generate endend
这段代码中, stub('customer')
和mmock('logger')
分别生成了2个test double
customer.stub(:name)
为customer double添加了一个method stub(打桩方法), :name为方法名 and_return('Aslak')
表示:name的返回值为Aslak
logger.should_receive(:log)
为logger double设置了一个对于message name()
的expectation
后面的generate()
方法里, 如果logger
对log()
的调用失败, 则整个example会fail
否则会判断logger.should_receive(:log)
后面的条件是否满足(此处为with(xxx)
,即log()
调用是否带参数xxx)
partial stubbing, partial mocking
12345678910111213141516171819202122232425
describe WidgetsController do describe "PUT update with valid attributes" it "finds the widget" widget = Widget.new() widget.stub(:update_attributes).and_return(true) Widget.should_receive(:find).with("37").and_return(widget) put :update, :id => 37 end it "updates the widget's attributes" do widget = Widget.new() Widget.stub(:find).and_return(widget) widget.should_receive(:update_attributes).and_return(true) put :update, :id => 37 end it "redirects to the list of widgets" widget = Widget.new() Widget.stub(:find).and_return(widget) widget.stub(:update_attributes).and_return(true) put :update, :id => 37 response.should redirect_to(widgets_path) end endend
更多关于Method Stubs
One-Line Shortcut
double()
,stub()
,mock()
第一个参数非必填但是强烈建议有, 因为其会作为失败时的消息
此外还可以接受一个hash作为第二参数
1
customer = double('customer', :name => 'Bryan')
等效于
12
customer = double('customer')customer.stub(:name).and_return('Bryan')
Implementation Injection
如果一个stub method需要使用多次而且根据条件不同会有不同返回值, 可以用如下方法
多用于before()
里
12345678
ages = double('ages')ages.stub(:age_for) do |what| if what == 'drinking' 21 elsif what == 'voting' 18 endend
方法链
12
article = double()Article.stub_chain(:recent, :published, :authored_by).and_return(article)
更多关于Message Expectations
执行次数
should_receive(:xxx)
要求xxx()
被调用且只调用一次, 如果希望调用若干次, 可采用下列方式
12345
mock_account.should_receive(:withdraw).exactly(5).timesnetwork_double.should_receive(:open_connection).at_most(5).timesnetwork_double.should_receive(:open_connection).at_least(2).timesaccount_double.should_receive(:withdraw).onceaccount_double.should_receive(:deposit).twice
如果期待方法不被调用,要使用should_not_receive
123
network_double.should_not_receive(:open_connection)network_double.should_receive(:open_connection).never #不推荐network_double.should_receive(:open_connection).exactly(0).times #不推荐
指定期待的参数, with()
1234567891011121314151617
### 指定一个参数, 且值为50account_double.should_receive(:withdraw).with(50)### 可以指定任意个参数checking_account.should_receive(:transfer).with(50, savings_account)### 第一个参数为给定值, 第二个参数为Fixnum型任意值source_account.should_receive(:transfer).with(target_account, instance_of(Fixnum))### 第一个参数可以为任意类型任意值source_account.should_receive(:transfer).with(anything(), 50)### 任意类型任意数量参数source_account.should_receive(:transfer).with(any_args())### 不传参数collaborator.should_receive(:message).with(no_args())### 参数为包含/不包含给定key/value的Hashwith(hash_including('Electric' => '123', 'Gas' => '234'))with(hash_not_including('Electric' => '123', 'Gas' => '234'))### 正则表达式mock_atm.should_receive(:login).with(/.* User/)
自定义的Argument Matchers
自定义一个类, 然后重写==(actual)
方法即可
也可以添加一个description()
方法以提供失败时输出的信息
1234567891011121314151617181920
class GreaterThanMatcher def initialize(expected) @expected = expected end def description "a number greater than #{@expected}" end def ==(actual) actual > @expected endenddef greater_than(floor) GreaterThanMatcher.new(floor)endcalculator.should_receive(:add).with(greater_than(37))
Throwing or Raising
and_raise()
可以不传参/一个参数(异常类或异常类实例)and_throw()
传symbol
1234567
account_double.should_receive(:withdraw).and_raiseaccount_double.should_receive(:withdraw).and_raise(InsufficientFunds)the_exception = InsufficientFunds.new(:reason => :on_hold)account_double.should_receive(:withdraw).and_raise(the_exception)account_double.should_receive(:withdraw).and_throw(:insufficient_funds)
按序执行
12
database.should_receive(:count).with('Roster', :course_id => 37).ordereddatabase.should_receive(:add).with(student).ordered
只要count()
在add()
之前执行就会pass
- RSpec::Mocks
- RSpec::Mocks中allow和allow_any_instance_of的区别
- RSpec
- rspec
- RSpec
- rspec
- Rhina.Mocks
- angular-mocks
- Stubs和Mocks区别 (Stubs vs. Mocks)
- 安装 Rspec
- 使用RSpec
- Rspec笔记
- rspec 测试
- Rspec简介
- ruby rspec
- RSpec簡介
- Rspec测试
- Rspec笔记
- UML初识
- CSDN简单安卓客户端实现
- HDU2845_Beans【不连续的最大子段和】【元素压缩】
- android Broadcast学习 实例
- 平衡二叉树
- RSpec::Mocks
- 如何使frameset框架的页面通过滚动条整体移动
- LINUX平台 java怎么直接连接access数据库dbf文件
- hdu 1527 取石子游戏(Wythoff Game/威佐夫博奕)
- 好的文章如何配上好标题
- WEB Face Tools
- Linux下 环境变量设置方法
- C++中的explicit关键字
- OpenCV图像处理车牌检测与定位应用