2014-09-05 51 views
1

在rspec的3.1.0中的语法,一个规范可以使用#allow存根的方法:能够想到一类

describe do 
    specify do 
    o = Object.new 
    allow(o).to receive(:foo) 
    o.foo 
    end 
end 

这工作得很好。但是,如果短线在一个类中的方法内,则#allow方法没有定义:

describe do 

    class Baz 
    def allow_bar(o) 
     allow(o).to receive(:bar) 
    end 
    end 

    specify do 
    o = Object.new 
    Baz.new.allow_bar(o) 
    o.bar 
    end 

end 

的错误是:

Failure/Error: allow(o).to receive(:bar) 
NoMethodError: 
    undefined method `allow' for #<Baz:0x8de6720> 
# ./bar_spec.rb:5:in `allow_bar' 
# ./bar_spec.rb:11:in `block (2 levels) in <top (required)>' 

为什么我在一个类中的磕碰

该测试将其测试double定义为常规类,而不是使用rspec的“double”方法。这是因为测试double有一个线程。内部测试双是这样的代码:

if command == :close 
    # Note: Uses the old (rspec 2) syntax. Needs to be converted 
    # to rspec 3 syntax using the #allow method. 
    socket.stub(:getpeername).and_raise(RuntimeError, "Socket closed") 
end 

这可以防止错误地使用套接字会话被关闭后,被测代码。

私有解决方案

我可以给测试双接入在RSpec中,模拟调用私有API来#allow:

class Baz 
    RSpec::Mocks::Syntax.enable_expect self # Uses private API 
    def allow_bar(o) 
     allow(o).to receive(:bar) 
    end 
    end 

这工作。然而,明确标记为RSpec的/嘲笑/ syntax.rb私有API:

# @api private 
    # Enables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc). 
    def self.enable_expect(syntax_host = ::RSpec::Mocks::ExampleMethods) 
    ... 

问题

在Rspec的3.1,有一个公共 API我可以用它来使期望类中可用的语法?

+1

应该有注入'socket'到类的方式。然后,你将不再需要在课堂中使用'allow'。 AFAIK RSpec 3试图尽可能多地删除猴子补丁,这是一件好事。这听起来像是一个懒惰的回答,但是当你的代码很难测试时,大多数情况下这是你的代码有其他问题的迹象。 – 2014-09-05 19:44:26

+0

@ p11y通常这是真的。我可能会在CR上发布完整的代码,看看其他人能否看到我看不到的更好的设计。 – 2014-09-05 19:55:25

+0

@ p11y我开始编写CR问题,然后实现了一个更好的方法(在这种情况下,公开两个私有方法做了窍门,对类的API没有真正的破坏)。另一个问题在询问中回答。谢谢你的帮助。我仍然对这个问题的答案感兴趣,因为下一次我想做错了。 – 2014-09-06 00:28:45

回答

1

您可以通过在几RSpec的模块/类混合到类实现这一点:

class MyClass 
    include RSpec::Mocks::ExampleMethods::ExpectHost 
    include RSpec::Matchers 

    def some_test 
    expect(1).to eql(1) 
    end 
end 
相关问题