鉴于以下代码:
(1)您如何编写规范来测试:allow_nil =>错误的选择?
(2)是否值得编写规范进行测试?
class Event < ActiveRecord::Base
belongs_to :league
delegate :name, :to => :league, :prefix => true, :allow_nil => false
end
describe Event do
context 'when delegating methods to league object' do
it { should respond_to(:league_name) }
end
end
如果你能扩展应该这样做,那将是很好的:
it { should delegate(:name).to(:league).with_options(:prefix => true, :allow_nil => false) }
答案 0 :(得分:9)
根据delegate
rails模块的文档:
如果委托对象为nil,则引发异常,无论nil是否响应委托方法,都会发生这种情况。您可以使用:allow_nil选项获取nil。
我会使用nil event
创建一个事件对象league
,或设置event.league = nil
,然后尝试调用event.name
,并检查它是否会引发异常,因为那就是当allow_nil
为假(这也是默认值)时应该发生的事情。我知道rspec有这个用于异常测试的习惯用语:
lambda{dangerous_operation}.should raise_exception(optional_exception_class)
我不确定是否应该有这个结构,尽管有are some articles, kinda old, about how to get this behavior in shoulda。
我认为这是值得测试的,如果是这个类的用户可以预期或假设会发生的行为 - 我认为在这种情况下可能是正确的。我不会扩展shoulda来测试“应该委托”,因为这似乎更依赖于实现:你真的说你的事件应该引发异常,如果你试图在{0}没有时调用{0}联赛。事件的用户对于如何实现这一点并不重要。我甚至会走得这么远,如果你想断言并记下这种行为,测试#name
与Event#name
具有相同的语义,没有提及任何关于League#name
,因为这是一种以行为为中心的方法。
根据代码的行为而不是如何构建代码来构建测试 - 以这种方式测试对于那些偶然进入测试的人来说是更好的文档,因为他们对“为什么我的事件会抛出?”这个问题更感兴趣。或“什么可能导致事件抛出?”比“这个活动委托吗?”。
如果以事件用户不应关心的方式更改代码,可以想象可能会发生什么样的故障,从而突出显示这种情况。如果他们不关心它,那么当你改变它时测试不应该破坏。例如,如果您希望自己处理委派,通过编写首先记录或递增计数器的delegate
函数然后然后委托给#name
,该怎么办?通过测试异常提升行为,您可以免受此更改的影响,但通过测试Event是否为委托,您将在进行此更改时中断该测试 - 因此您的测试并未查看的确切内容对league
的调用很重要。
无论如何,这只是肥皂盒谈话。 tl; dr:测试它是否是某人可能依赖的行为。任何未经测试的东西都是Shroedinger的猫:破碎而不是同时破碎。说实话,大部分时间都可以这样:无论你是想对系统应该如何表现,还是只是让它成为“未指明的行为”,这是一个品味问题。
答案 1 :(得分:3)
关于是否要对此进行测试,这里有几件事情:
1)我不认为指出这种行为有什么不妥。如果您的用户需要了解您的软件/库,那么通常非常有助于确保您的公共合同中包含的所有方法都是规范的。如果您不想将此模型的api作为此部分的一部分,我可能会建议手动执行委派,以便不向您提供比您需要的更多方法。
2)此类规范有助于确保您所委托的对象的合同仍然得到执行。如果您在测试中使用存根和模拟,这尤其有用,因为它们通常实现相同的合同,因此至少您知道此合同何时更改。
就你如何测试它的allow_nil部分而言,我同意马特,最好的想法是确保联盟为零,然后尝试在联赛上打电话。您可以测试以确保返回nil。
希望这有帮助。
答案 2 :(得分:0)
由于我们创建的效率是两个类之间的合同,所以我将对委托进行测试
describe '#league_name' do
let(:event) { create(:event) }
after { event.league_name }
it "delegates to league's name with prefix" do
expect(event.league).to receive(:name)
end
end