2010-11-11 2 views
45

У меня есть модель с приватным методом. Я хотел бы специфицировать RSpec,
Как вы обычно это делаете? Вы только проверяете метод вызова частного?
или также специфицировать частный? если да, как вы поживаете?Как специфицировать частный метод

ответ

109

Я всегда придерживаюсь такого подхода: Я хочу проверить публичный API, который предоставляет мой класс.

Если у вас есть частные методы, вы вызываете их только из общедоступных методов, которые вы публикуете другим классам. Следовательно, если вы проверите, что эти общедоступные методы работают как ожидалось при любых условиях, вы также доказали, что частные методы, которые они используют, также работают.

Я признаю, что столкнулся с некоторыми особенно сложными частными методами. В этом крайнем случае, если вы хотите, чтобы проверить их, вы можете сделать это:

@obj.send(:private_method) 
+1

Спасибо за вашу помощь, я согласен, что тестирование общественного метода доказывает, что частный работает тоже. Это, как говорится, я действительно хочу проверить частный метод, и ваше решение работает как шарм, спасибо! – Mike

+2

Вот еще один интересный подход http://kailuowang.blogspot.com/2010/08/testing-private-methods-in-rspec.html – gucki

+1

У меня есть крюк before_save в моей модели, который сохраняет частный токен в базу данных через приватный 'make_private_token'. Метод make_private_token использует методы открытого класса, а не наоборот, поэтому единственный способ проверить его - с помощью метода 'send'. Не видите ничего «экстремального» об этом ... – Starkers

6

Для частных методов, которые нуждаются покрытия кода (временно или постоянно), использовать rspec-context-private gem временно сделать частные методы общественности в контексте.

gem 'rspec-context-private' 

Работает, добавив общий контекст в ваш проект.

RSpec.shared_context 'private', private: true do 

    before :all do 
    described_class.class_eval do 
     @original_private_instance_methods = private_instance_methods 
     public *@original_private_instance_methods 
    end 
    end 

    after :all do 
    described_class.class_eval do 
     private *@original_private_instance_methods 
    end 
    end 

end 

Затем, если вы передаете :private как метаданные к describe блока, частные методы будут общественности в этом контексте.

class Example 
    private def foo 
    'bar' 
    end 
end 

describe Example, :private do 
    it 'can test private methods' do 
    expect(subject.foo).not eq 'bar' 
    end 
end 
+0

Не знаю, поддерживаете ли вы этот драгоценный камень больше, но в вашей документации нет блока кода об объявлении shared_context. Поэтому я не смог заставить его работать, просто прочитав документацию. После добавления в этот блок он работает как ожидалось. – istrasci

0

Если Вы желаете испытать ожидание на частный метод, принятый ответ не будет действительно работать (по крайней мере, не то, что я знаю, так что я открыт для коррекции по этому вопросу). Что я сделал вместо этого даже грязнее - в самом тесте, просто выставить метод, пересматривая его:

def object_to_test.my_private_method 
    super 
end 

Работы на Ruby 1.8, не может прокомментировать любой из новых сред выполнения.

Смежные вопросы