我有一个带有location
方法的模型Family,该方法合并了其他对象Members的location
输出(Members与Family相关联,但这在这里并不重要)。
例如,给定
- member_1具有
location
=='圣地亚哥(出差,5月15日返回)' - member_2具有
location
=="圣地亚哥"
位置可能返回"San Diego(member_1 traveling,returns 15 May)"具体信息并不重要。
为了简化Family. location的测试,我想stub Member.location。但是,我需要它返回两个不同的(指定的)值,如上面的例子所示。理想情况下,这些值将基于member
的属性,但是简单地返回不同的值也可以。在RSpec中有办法做到这一点吗?
可以在每个测试示例中重写Member.location方法,例如
it "when residence is the same" do
class Member
def location
return {:residence=>'Home', :work=>'his_work'} if self.male?
return {:residence=>'Home', :work=>'her_work'}
end
end
@family.location[:residence].should == 'Home'
end
但我怀疑这是不是一个好的实践,无论如何,当RSpec运行一系列示例时,它不会恢复原来的类,所以这种覆盖会"毒害"后续的示例。
那么,有没有办法让stubed方法在每次调用时返回不同的指定值呢?
6条答案
按热度按时间v9tzhpje1#
您可以存根一个方法,以便在每次调用它时返回不同的值;
因此,第一次调用
@family.location
时,它将返回“first”,第二次调用时,它将返回“second”,之后的所有调用都将返回“other”。34gzjxbg2#
RSpec 3语法:
ars1skjm3#
公认的解决方案应该只在你有一个特定的调用次数和需要一个特定的数据序列时使用。但是如果你不知道将要进行的调用次数,或者不关心数据的顺序只是每次都不同呢?正如OP所说:
只需在序列中返回不同的值即可
and_return
的问题是返回值是记忆的,这意味着即使你返回动态的东西,你得到的总是一样的。例如
或者,一个实际的例子是使用工厂并获得相同的ID:
在这些情况下,您可以存根方法主体,以便每次都执行代码:
注意,在这个上下文中,您不能通过
self
访问Member对象,但是可以使用测试上下文中的变量。例如
toe950274#
如果出于某种原因要使用旧语法,您仍然可以:
vohkndzv5#
我已经尝试了上面的解决方案,但是它对我的不起作用。我用一个替代实现来解决这个问题。
例如:
bqjvbblv6#
我遇到了一个问题,我多次调用一个方法,而且顺序不总是相同的,在这种情况下,我建议使用
.with
,使用方法的参数来区分示例。例如,这可能是您的“默认”返回值:
但是,如果location接收到像“male”这样的参数,则可以添加:
有许多不同的匹配参数类型可以用于
.with
:https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/setting-constraints/matching-arguments