2017-03-07 56 views
0

按照rspec expect message docs,当我们使用如下代码:Rspec的期望接收(...)与(TIME_RANGE)

expect(double).to receive(:message).with(argument) 

argument响应#===,Rspec的将呼吁任何argument.===在实际传递但是如果我想检查一段时间是否真的被传入了,我该怎么办?

例如,我想测试,这种方法将正确的信息以正确的参数(它简化):

def in_date_range(range) 
    activities.by_created_at(range) 
end 

像一个测试:

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: can't iterate from Time

我怀疑这是因为哪个rspec试图在我的时间范围内拨打#===并遇到麻烦。

有没有办法检查我的时间范围实际上是我通过的范围?

我实际上并不是在寻找重叠的时间,而是范围是相同的:它们具有相同的开始点和结束点。

我想我们可以做到这一点的一种方式是编写自定义匹配器,但它似乎是一个不寻常的路线。

EDIT

另一种可能的解决方案是将方法分成两个部分:

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 

然后我可以测试,它返回适当的范围内计算方法,并且对于较大的方法予可以在正确的输入中进行测试,并将取得的结果从较小的方法的输出转换为另一种方法,避开消息中检查范围的混淆。

这并没有完全回答这个问题 - 你如何使用rspec receive(:message)检查'接收特定范围',但现在对我来说已经足够了。

回答

0

编辑:

我有一点更多的时间来看看这个,我认为错误在于某处activities.by_created_at(range)内。这必须试图调用范围内的循环。

下面是通过规格。我一直反对它创建一个虚拟Thing类和运行测试,一切都经过:

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 

问题是与制作时间迭代。

看到这个问题:Iterate over Ruby Time object with delta

接受的答案的第二部分应该帮助你。

+0

哦有趣的完全发生

A发生!我不知道为什么我没有检查。这流露出一些光芒。编辑指定时间实例的问题,虽然我不明白时间迭代的相关性 –

0

makandracards

测试如果两个日期范围在Ruby或Rails的重叠

甲检查,如果两个日期或时间范围A和B的重叠需要覆盖很多情况下:

A部分重叠B A围绕B B围绕A A完全发生在B B之后完全发生在A 一个技巧涵盖所有这些c单个表达式的检查是查看每个范围的开始日期是否在同一方向上查看另一个范围的结束日期。

下面的代码显示了如何在Ruby on Rails中实现此功能。该示例是一个类Interval,它具有两个属性#start_date和#end_date。这些日期被认为是包容性的,这意味着如果一个间隔在另一个间隔开始的那天结束,我们认为这两个间隔重叠。

注意我们如何为加载的Ruby对象(Interval#overlappings?)和返回所有重叠间隔(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 

算法

你能想象的算法是这样的解释:“如果两个范围的开端看其他范围的结束,难道他们都在同一个方向看? “

如果您在一张纸上画,你可以看到,这种说法是对其中两个范围重叠的所有情况下都是这样:

一个部分重叠乙 包围着乙 乙围绕 你也可以看到,该声明是虚假的,其中范围不重叠:乙 后完全B之后一个

+0

啊,不幸的是,我不清楚我的问题。我不是在寻找一个时间在某个时间范围内的测试,而是一个范围等于另一个范围。 –

+0

如果你看,这就是这样。它比较两组开始和两组结束。 – OneNeptune

+0

当我说'平等'我的意思是'开始时间是一样的,结束时间是一样的'。你的函数检查重叠,除非我完全误解了它。 我很欣赏那种优雅的数学。这是一个干净的解决方案,不幸的是,这不是我的问题。 –