Каков самый современный способ озвучивания / насмешки метода в контроллере Rails с использованием RSpec? - PullRequest
0 голосов
/ 19 декабря 2018

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

Однако, читая документацию rspec 3.8 , он говорит следующее:

  • API rspec-mocks разработан для отдельных экземпляров объектов, но эта функция работает с целыми классами объектов.В результате есть некоторые семантически запутанные крайние случаи.Например, вределите в require_any_instance_of (Widget) .to receive (: name) .twice неясно, ожидается ли, что конкретный экземпляр получит имя дважды, или ожидаются два полученных итога.(Это первое.)
  • Использование этой функции часто является запахом дизайна.Возможно, ваш тест пытается сделать слишком много или тестируемый объект слишком сложен.
  • Это самая сложная функция rspec-mocks, и в прошлом она получала большинство сообщений об ошибках.(Никто из основной команды не использует его активно, что не помогает.)

Каков правильный и «современный» способ смоделировать метод в спецификации запроса?

Не думаю, что имеет значение следующее, но на всякий случай:

  • Rails 5.2
  • Ruby 2.4.1
  • RSpec 3.8

Редактировать: добавление некоторого примера кода.

module A
  def my_pain
    puts "I don't want to run this during testing"
  end
end

class TestController < ApplicationController
  include A
  def index
    my_pain
  end
end

Итак, каков современный способ проверки "#index" во время насмешки над "#my_pain" с RSpec в тесте контроллера / запроса.

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Другой подход - стараться высмеивать как можно меньше.

  • Ничего не имитировать, пока тесты не станут медленными или не потребуются внешние ресурсы для настройки.
    Затем имитируют только медленные зависимости или классы или обращаются к внешним ресурсам (веб-сервис, файловая система и т. Д.)

  • Ничего не проверяйте, пока настройка теста не станет очень сложной.
    Затем смоделируйте зависимости, которые содержат очень сложную логику, чтобы упростить / уменьшить количество логических ветвей для проверки.

В случае, если вы решили смоделировать некоторые из зависимостей:
Если экземпляр зависимости предоставлен классу при тесте

class Order
    def initialize(printer)
        @printer = printer
    end

    def print
        @printer.print("my-printer", self)
    end
end

# Test
RSpec.describe "Order.print" do
    it "prints order to my printer" do
        fake_printer = double("Printer", :print => nil)
        order = Order.new(fake_printer)

        expect(fake_printer).to receive(:print).with("my-printer", order)

        order.print
    end
end

Если экземпляр зависимости создан внутри класса при тесте

class Order
    def initialize
        @printer = Printer.new("my-printer")
    end

    def print
        @printer.print(self)
    end
end

# Test
RSpec.describe "Order.print" do
    it "prints order to my printer" do
        fake_printer = double("Printer", :print => nil)
        allow(Printer).to receive(:new).with("my-printer").and_return(fake_printer)

        order = Order.new

        expect(fake_printer).to receive(:print).with(order)

        order.print
    end
end

Обратите внимание, что при использовании double("ClassName") необходимо настроить все методы, которые будут вызываться во время теста, если нет - будет выдано исключение.

RSpec Test Doubles

0 голосов
/ 19 декабря 2018

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

...