Используя rspec, не понимаете разницы между макетом и объектом-заглушкой?

#ruby-on-rails #rspec

#ruby-on-rails #rspec

Вопрос:

В чем разница между макетом и заглушкой, они оба кажутся мне очень похожими?

Было бы неплохо, если бы кто-нибудь мог привести реальный пример того, когда что использовать, или они взаимозаменяемы, но есть лучшая практика, например, когда использовать макет или заглушку?

Ответ №1:

Это ссылка в большинстве статей, довольно общее и понятное объяснение:

http://martinfowler.com/articles/mocksArentStubs.html

В двух словах:

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

И

Макеты — это объекты, предварительно запрограммированные с ожиданиями, которые формируют спецификацию вызовов, которые они должны получать.

Комментарии:

1. Понятно, поэтому используйте mocks, когда хотите убедиться, что объект вызывается определенным образом … и заглушки для готовых ответов.

Ответ №2:

Предоставленная статья и заданный вопрос взяты из разных контекстов. Что касается области Rspec, авторы книги Rspec пишут в главе 14.1:

«Чтобы создать double, просто используйте double() метод, подобный этому:

 thingamajig_double = double('thing-a-ma-jig')
  

… Существуют также методы stub() и mock() , которые создают объект того же типа:

 stub_thingamajig = stub('thing-a-ma-jig')
mock_thingamajig = mock('thing-a-ma-jig')
  

Мы можем использовать их, чтобы при необходимости сделать спецификацию более понятной «. (курсив мой)

Авторы также включают фрагмент кода позже в главу 14.3 —

 describe Statement do
  it "logs a message on generate()" do
    customer = stub('customer')
    customer.stub(:name).and_return('Aslak')
    logger   = mock('logger')
    statement = Statmement.new(customer, logger)

    logger.should_receive(:log).with(/Statement generated for Aslak/)

    statement.generate
  end
end
  

и затем напишите «Используя mock() метод для генерации двойного регистратора и stub() метод для генерации двойного клиента, мы помогаем выразить, что эти объекты играют разные роли в примере». (курсив мой)

Эти фрагменты кода и пояснения приводят меня к мысли, что, хотя концептуальные линии, нарисованные мистером Фаулером в его статье, хороши для рисования, между or (или stub() , если уж на то пошло) в Rspec нет mock() функциональной double() разницы. Может быть и неправильно, я не проверял документацию.

Ответ №3:

 stub:

A fake object that returns a pre-determined value for a method call.
Actual object is not called.


Stubs and mocks often used interchangeably.
Mean two different things.
But people generally refer to "Mock Object Frameworks"

Product.stub(:find_by_title).with('orange').and_return(Product.new(:title=>"orange", :price=>6.23))

Mocks:

Just like Stubs, but with an expectation to be (or not to be) called.

Test will fail if the mock is (or isn't) called.

Used in the same way as stubs,

Product.should_receive(:find_by_title).with('orange').exactly(2).and_return(Product.new(:title=>"orange", :price=>6.23))

To know more about mock and stub please refer this article, 
http://www.ibm.com/developerworks/web/library/wa-mockrails/index.html