2017-04-27 44 views
-2

我如何可以模拟调用函数说法,我与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)

+0

你好,你能否添加更多信息你得到的错误? – Bohdan

+0

我更新了我的帖子 – andgursky

+0

http://stackoverflow.com/help/accepted-answer – engineersmnky

回答

1

不知道为什么你要这样理解,但你是不是太遥远。

目前,你要使用

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_classallow(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不再存在,会发生什么?)

相关问题