Ruby on rails Rspec预期接收(…)。带有(时间范围)
根据,当我们使用如下代码时:Ruby on rails Rspec预期接收(…)。带有(时间范围),ruby-on-rails,ruby,rspec,Ruby On Rails,Ruby,Rspec,根据,当我们使用如下代码时: expect(double).to receive(:message).with(argument) 而参数响应#===,Rspec将调用参数。===处理实际传入的任何内容。但是如果我想检查一系列的时间是否真的传入了,我该怎么办呢 例如,我想测试此方法是否使用正确的参数发送正确的消息(已简化): 还有一个测试,比如: it 'passes correct arguments' do range = Time.new(0)..(Time.new(0) + 1.h
expect(double).to receive(:message).with(argument)
而参数
响应#===
,Rspec将调用参数。===
处理实际传入的任何内容。但是如果我想检查一系列的时间是否真的传入了,我该怎么办呢
例如,我想测试此方法是否使用正确的参数发送正确的消息(已简化):
还有一个测试,比如:
it 'passes correct arguments' do
range = Time.new(0)..(Time.new(0) + 1.hour)
expect(activities).to receive(:by_created_at).with(range)
in_date_range(range)
end
此操作失败,出现TypeError:无法从时间开始迭代
我怀疑这是因为哪个rspec试图在我的时间范围内调用#=
,结果遇到了麻烦
有没有办法检查我的时间范围实际上就是我通过的时间范围
我并不是在寻找重叠的时间,而是寻找相同的范围:有相同的起点和终点
我想我们可以这样做的一种方法是编写一个自定义匹配器,但这似乎是一种不寻常的方法
编辑
另一种可能的解决方案是将该方法分为两部分:
def compute_range(time_in)
(computations)
time1..time2
end
def in_date_range(time_in)
range = compute_range(time_in)
activities.by_created_at(range)
end
然后我可以测试compute方法,它返回正确的范围,对于我可以测试的较大的方法,它传入正确的输入,并获取较小方法的输出,它从第一个方法获取结果并传入另一个方法,避免了在消息中检查范围的混乱
这并没有完全回答这个问题-如何用rspec receive(:message)检查“接收特定范围”,但现在对我来说已经足够了 编辑:
我有更多的时间来研究这个问题,我认为错误在活动中的某个地方。这一定是在尝试调用范围上的循环
下面是通过的规格。我创建了一个虚拟的东西类并对其运行测试,所有测试都通过了:
class Thing
def initialize( name )
@name = name
end
def in_date_range(range)
activities.by_created_at(range)
end
end
describe Thing do
specify 'Thing test' do
name = 'Tim'
expect(Thing).to receive(:new).with( name )
Thing.new(name)
end
specify 'Time test' do
range = Time.new(0)..(Time.new(0) + 1.hour)
t = Thing.new('Jimmy')
expect(t).to receive(:in_date_range).with( range )
t.in_date_range( range )
end
end
~/test (master)
18:22:21$ rspec spec/models/thing_spec.rb
Loading Enhanced Logger.
Run options: include {:focus=>true}
..
Finished in 0.14094 seconds (files took 2.89 seconds to load)
2 examples, 0 failures
结束编辑
问题不在于rspec检查范围
我运行了这个,它成功了:
describe Thing do
specify 'Thing test', :focus do
range = 1..4
expect(Thing).to receive(:new).with( range )
Thing.new(1..4)
end
end
Run options: include {:focus=>true}
.
Finished in 0.09132 seconds (files took 2.59 seconds to load)
1 example, 0 failures
问题在于让时间变得不可忍受
见这个问题:
接受答案的第二部分应该对您有所帮助。来源:
在Ruby或Rails中测试两个日期范围是否重叠
检查两个日期或时间范围A和B是否重叠需要涵盖很多情况:
A与B部分重叠
A围绕着B
B围绕着A
A完全发生在B之后
B完全发生在A之后
用一个表达式覆盖所有这些情况的一个技巧是查看每个范围的开始日期是否在同一方向上看另一个范围的结束日期
下面的代码展示了如何在RubyonRails中实现这一点。示例是一个类间隔,它有两个属性#start#u date和#end#u date。这些日期被认为是包含的,这意味着如果一个间隔在另一个间隔开始的一天结束,则我们认为这两个间隔重叠。
请注意,我们如何为加载的Ruby对象实现一个版本(Interval#overlaps?)和一个返回所有重叠间隔(Interval.overlapping)的范围。根据您的问题,您可能需要一个或两个或这些
class Interval < ActiveRecord::Base
validates_presence_of :start_date, :end_date
# Check if a given interval overlaps this interval
def overlaps?(other)
(start_date - other.end_date) * (other.start_date - end_date) >= 0
end
# Return a scope for all interval overlapping the given interval, including the given interval itself
named_scope :overlapping, lambda { |interval| {
:conditions => ["id <> ? AND (TIMEDIFF(start_date, ?) * TIMEDIFF(?, end_date)) >= 0", interval.id, interval.end_date, interval.start_date]
}}
end
类间隔=0
结束
#返回与给定间隔重叠的所有间隔的范围,包括给定间隔本身
命名_范围:重叠,lambda{|区间|{
:条件=>[“id”和(TIMEDIFF(开始日期),*TIMEDIFF(?,结束日期))>=0”,interval.id,interval.end\u日期,interval.start\u日期]
}}
结束
算法说明
您可以这样描述算法:“如果两个范围的起点都指向另一个范围的终点,那么它们是否都指向同一方向?”
如果你在一张纸上画画,你可以看到这句话适用于两个范围重叠的所有情况:
A与B部分重叠
A围绕着B
B围绕着A
您还可以看到,如果范围不重叠,则该语句为false:
A完全发生在B之后
B完全发生在A之后当然,您可以只期望(..)。接收(:foo){arg | do|u something}
并在do|u something块中检查您的期望。以下方面应起作用:
range = Time.new(0)..(Time.new(0) + 1.hour)
expect(activities).to receive(:by_created_at) { |arg|
expect(arg.first).to eq(Time.new(0))
}
这是因为失败的expect会引发特定于rspec的异常,并且rspec运行程序不关心在执行过程中会在何处引发此类异常,只要它是在执行it
块期间 哦,有趣!我不知道为什么我没有检查。这有点道理。问题经过编辑以指定时间实例,虽然我不理解将时间设置为iterableAh的相关性,但不幸的是,我对我的问题不够清楚。我不是在寻找一个测试,一个时间在某个时间范围内,而是一个时间范围等于另一个时间范围。如果你看,这个测试就是这样。它比较两组开始和两组结束。当我说“相等”时,我的意思是“开始时间相同,结束时间相同”。你的函数检查重叠,除非我完全误解了它。顺便说一下,我欣赏优雅的数学。这是你问题的一个干净的解决方案,不幸的是,这不是我的问题。
range = Time.new(0)..(Time.new(0) + 1.hour)
expect(activities).to receive(:by_created_at) { |arg|
expect(arg.first).to eq(Time.new(0))
}