2014-09-05 2 views
1

В RSpec 3.1.0, спецификацию можно использовать # Разрешить незавершенный метод:Включения ожидать синтаксис в классе

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

Это прекрасно работает. Однако, если заглушка находится в пределах метода в классе, то метод # Разрешить не определен:

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. Это связано с тем, что у тестового двойника есть поток. Внутри двойной тест этот код:

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 

Это предотвращает код тестируемых от ошибочного использования сокета после сессии была закрыта.

Частное решение

Я могу дать двойной тест доступ к # Разрешить по телефону частный API в RSpec-макет:

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

Это работает. Тем не менее, он явно помечены как частное API в RSpec/издевается/syntax.rb:

# @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 пытается удалить как можно больше патчей обезьян, что хорошо. Это звучит как ленивый ответ, но когда ваш код трудно проверить, большую часть времени это знак того, что ваш код имеет некоторые другие проблемы. –

+0

@ p11y Это обычно так. Я могу опубликовать полный код CR и посмотреть, сможет ли кто-нибудь увидеть лучший дизайн, который я не вижу. –

+0

@ p11y Я начал писать CR вопрос, а затем понял, что лучший способ (в данном случае, создание двух частных методов общественности сделал трюк, без реального ущерба API класса). Еще один вопрос ответил на вопрос. Спасибо за вашу помощь. Меня все еще интересует ответ на этот вопрос, потому что в течение одного раза я хочу сделать это неправильно. –

ответ

1

Вы можете сделать это путем смешивания нескольких RSpec модулей/классов в классе:

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

    def some_test 
    expect(1).to eql(1) 
    end 
end