RSpec的模拟调用函数的参数
我如何可以模拟调用函数说法,我与RSpec的测试 我做这样的:RSpec的模拟调用函数的参数
module Module1
def find_item(str, item_class)
arr = item_class.find_or_initialize_by(...)
end
end
然后在规格:
let!(:dummy_class) { Class.new { extend Module1 } }
it 'calls find_or_initialize_by' do
item_class = double("Item")
allow(dummy_class).to receive(:item_class).and_return(item_class)
expect(item_class).to receive(:find_or_initialize_by)
dummy_class.find_item("item1", Item)
end
它提出了一个错误“#不执行:item_class” 我试图使用class_double和instance_double,但它是无益的。
Failures:
1) Module1#find_items Failure/Error: allow(dummy_class).to receive(:item_class) # does not implement: item_class # ./spec/..._spec.rb:26:in `block (3 levels) in '
26行:允许(dummy_class)。为了接收(:item_class).and_return(item_class)
不知道为什么你要这样理解,但你是不是太遥远。
目前,你要使用
allow(dummy_class).to receive(:item_class).and_return(item_class)
但item_class
是不是只是一个local_variable
的方法。
Message Allowance语法简而言之就是allow(object).to receive(method_name).with(arguments).and_return(return_value)
和Message Expectation语法是expect(object).to receive(method_name).with(arguments).and_return(return_value)
因此,也许你的意思是allow(dummy_class).to receive(:find_item).with(item_class).and_return(item_class)
因为find_item
是方法实际上是被称为和item_class
传入的说法,但因为你是剔除返回值,那么方法的主体永远不会发生。
进一步你可以allow(dummy_class).to recieve(:find_item).and_call_original
但这并不是真正的目的,因为dummy_class
是不是一个双重的,并已被允许调用其原始版本find_item
。
因此,让我们使用dummy_class
和allow(item_class).to receive(:find_or_initialize_by)
的本机功能,然后下面的工作。
it 'calls find_or_initialize_by' do
item_class = double("Item")
allow(item_class).to recieve(:find_or_initialize_by) #needed because it is a test double and knows nothing
expect(item_class).to receive(:find_or_initialize_by)
dummy_class.find_item("item1", item_class) #used test double here to trap messages
end
替代地,我们可以使用的Item
部分双键和跳过Test Doubleitem_class
例如
#please note this binds the test to Item existing
it 'calls find_or_initialize_by' do
allow(Item).to receive(:find_or_initialize_by) #now a stubbed method on a partial double(Item)
expect(Item).to receive(:find_or_initialize_by)
dummy_class.find_item("item1", Item) #used the partial double
end
Partial doubles是好的,因为它们可以验证双打和将确保Object
实际上定义磕碰之前该方法。
如此说来给你测试的性质和事实dummy_class
是不是双(因此没有必要allow
任何东西),你是不会测试任何返回值就按这个,我只想用Spy,因为他们建议只是为了消息的期望。 它使测试更简单,更清晰,无任何依赖关系:
it 'calls find_or_initialize_by' do
item = spy("item")
dummy_class.find_item("item1", item)
expect(item).to have_received(:find_or_initialize_by)
end
他们有部分双味太但这是依赖于Item
被已知并加载Object
:(非常类似于以上,但预期是一种
#please note this binds the test to Item existing
it 'calls find_or_initialize_by' do
allow(Item).to receive(:find_or_initialize_by)
dummy_class.find_item("item1", Item)
expect(Item).to have_received(:find_or_initialize_by)
end
另外让通话效果)后,我们假设在Module1
的(...)
看起来像name: str
那么我会建议测试,以及它被称为以正确的参数如
it 'calls find_or_initialize_by with args' do
item = spy("item")
dummy_class.find_item("item1", item)
expect(item).to have_received(:find_or_initialize_by).with(name: 'item1')
end
这可以确保不仅可以进行呼叫,而且可以将预期的参数传递给呼叫。
特别是随着消息的预期的Module
测试中,我会尽量保持测试双打和间谍,因为它使独立和快速测试(当Item
不再存在,会发生什么?)
你好,你能否添加更多信息你得到的错误? – Bohdan
我更新了我的帖子 – andgursky
http://stackoverflow.com/help/accepted-answer – engineersmnky