2013-04-06 1 views
16

Я расширяю существующую библиотеку, создавая дочерний класс, который распространяется на класс библиотеки.Как я могу высмеять супер в ruby ​​с помощью rspec?

В классе ребенка я смог протестировать большую часть функциональности в методе initialize, но не смог высмеять super. Детский класс выглядит примерно так.

class Child < SomeLibrary 
    def initialize(arg) 
     validate_arg(arg) 
     do_something 
     super(arg) 
    end 

    def validate_arg(arg) 
     # do the validation 
    end 

    def do_something 
     @setup = true 
    end 
end 

Как я могу написать RSpec тест (с мокко), что я могу издеваться super вызов? Обратите внимание, что я тестирую функциональность метода initialize в классе Child. Должен ли я создавать отдельный путь кода, который не вызывает super, когда ему предоставляется дополнительный аргумент?

ответ

15

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

Вместо этого выясните, какое поведение этого класса изменится, если отсутствует вызов super, и напишите пример, который выполняет и проверяет это поведение.

+1

Означает ли это, я не могу писать RSpec тест для инициализации? Является ли плохой практикой писать модульный тест для метода инициализации? Кстати, я расширяю библиотеку соединителей базы данных. Если я не пишу модульный тест, но напишу интеграционный тест, я просто думаю, что это странно, если для проверки rspec требуется подключение к реальной базе данных. –

+0

Мне не имеет смысла, почему мы не можем высмеивать супер. Кажется полезным сделать это, чтобы правильно протестировать поведение инициализации в изоляции, и, несомненно, супер - это сообщение, отправленное в экземпляр класса, нет? –

+1

Нет, 'super' - _not_ сообщение, отправленное экземпляру класса. Я не знаю никаких конструкций метапрограммирования ruby, которые бы сделали это возможным, и даже если бы это было так, я все еще не убежден, что это хорошая идея. –

1

Хороший способ проверить это, чтобы установить ожидание какого-либо действия, предпринятые суперкласса - например:

class Some::Thing < Some 
def instance_method 
    super 
end 
end 

и супер класс:

class Some 
    def instance_method 
    another_method 
    end 

    def self.another_method # not private! 
    'does a thing' 
    end 
end 

Теперь тест:

describe '#instance_method' do 
    it 'appropriately triggers the super class method' do 
     sawm = Some::Thing.new 
     expect(sawm).to receive(:another_method) 
     sawm.instance_method 
    end 
end 

Все это определяет, что супер был назван над суперклассом

Полезность этого шаблона зависит от того, как вы структурируете свои тесты/какие ожидания у вас есть мутации типа child/производного класса с помощью применяемого метода super.

Также - обратить пристальное внимание на class и instance методов, вам нужно будет настроить allows и expects соответственно

YMMV