Подтвердить что ты не робот

Что такое двойной метод в rspec?

В rspec doc указано, что для создания теста double я должен использовать метод double. Но я вижу, что он работает нормально, даже если я не использую double. Есть ли что-то неправильное, если вы не используете double? Также, если я не использую double, как MyClass получает stub и другие методы rspec? Доступны ли они для всех объектов при работе в rspec?

require 'spec_helper'

class MyClass

    def self.run
        new.execute
    end

    def execute
        'foo'
    end

end

describe MyClass do

    it 'should stub instance method' do
        obj = MyClass.new
        obj.stub(:execute).and_return('bar')
        obj.execute.should == 'bar'
    end

    it 'should stub class method' do
        MyClass.stub(:run).and_return('baz')
        MyClass.run.should == 'baz'
    end

end
4b9b3361

Ответ 1

Изменить: я просто перечитал ваш вопрос и понял, что не совсем ответил на него. Оставляя свой первоначальный ответ, потому что это связано, но вот ваш конкретный ответ:

Причина, по которой вам не нужна двойка, - это то, что вы ставите методы класса, а не методы экземпляра. double полезен только для работы с экземплярами класса, а не с самим классом.

Старый ответ, в котором объясняется двойное:

Вы всегда должны использовать реальные классы вместо двойных тестов, когда сможете. Это будет больше использовать ваш код и сделать ваши тесты более полными. Тестовые двойники используются в ситуациях, когда вы не можете или не должны использовать реальный объект. Например, если класс не может быть создан без использования внешнего ресурса (например, сети или базы данных) или имеет большое количество зависимостей, и вы просто проверяете что-то, что его использует, вы можете создать double и заглушите несколько методов на двойном.

Вот более конкретный пример: скажем, вы тестируете MyClass, но для того, чтобы создать экземпляр MyClass, вам нужно передать в FooLogger:

mylogger = FooLogger.new
myclass = MyClass.new logger: mylogger

Если FooLogger.new открывает сокет syslog и сразу начинает рассылать спам, каждый раз, когда вы запускаете тесты, вы регистрируетесь. Если вы не хотите спамить ваши журналы во время этого теста, вместо этого вы можете создать double для FooLogger и наложить на него метод:

mylogger = double(FooLogger)
mylogger.stub(:log)
myclass = MyClass.new logger: mylogger

Поскольку большинство хорошо продуманных классов могут быть созданы без каких-либо побочных эффектов, вы обычно можете просто использовать реальный объект вместо двойного и вместо этого использовать методы заглушки. Существуют и другие сценарии, в которых классы имеют множество зависимостей, которые затрудняют их создание, а двойники - это путь преодоления крутильного состояния и проверка того, что вам действительно нужно.

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

Ответ 2

С RSpec Mocks 3.0 изменилось поведение двойников. Теперь вы можете проверить удвоение, что означает, что RSpec проверит, что методы если они доступны ", но" проверка не произойдет, если базовый объект или класс не определены ".

Проверяя двойные запросы, вы должны быть конкретными относительно двойного типа (экземпляр, класс, объект, динамический класс, частичный). Ниже приведен пример из RSpec Relish для экземпляра double:

RSpec.describe User, '#suspend!' do
  it 'notifies the console' do
    notifier = instance_double("ConsoleNotifier")

    expect(notifier).to receive(:notify).with("suspended as")

    user = User.new(notifier)
    user.suspend!
  end
end