Мокающие конструкторы в Ruby

Я Java-разработчик, играющий с Ruby, и мне он нравится. Я понял, что благодаря средствам метапрограммирования Ruby мои модульные тесты стали намного чище, и мне не нужны неприятные фреймворки для имитации. У меня есть класс, которому нужны службы класса File, и в моем тесте я не хочу трогать свою настоящую файловую систему. В Java я бы использовал некоторую виртуальную файловую систему для упрощения «швов» для передачи фальшивых объектов, но в Ruby это явно излишне. То, что я придумываю, кажется уже действительно приятным по сравнению с миром Java. В моем тестируемом классе у меня есть необязательный параметр конструктора:

def initialize(file_class=File)

Когда мне нужно открыть файлы в моем классе, я могу сделать это:

@file_class.open(filename)

И вызов идет либо к настоящему файловому классу, либо, в случае моего модульного теста, к поддельному классу, который не касается файловой системы. Я знаю, что должен быть лучший способ сделать это с помощью метапрограммирования?

Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
4
0
5 137
3

Ответы 3

Mocha (http://mocha.rubyforge.org/) - очень хорошая имитирующая библиотека для Ruby. В зависимости от того, что вы на самом деле хотите протестировать (например, если вы хотите просто подделать вызов File.new, чтобы избежать зависимости файловой системы, или если вы хотите убедиться, что правильные аргументы передаются в File.new), вы можете сделать что-то вроде этого:


require 'mocha'

mock_file_obj = mock("My Mock File") do
  stubs(:some_instance_method).returns("foo")
end

File.stubs(:new).with(is_a(String)).returns(mock_file_obj)

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

auramo 16.09.2008 17:43

Я не вижу необходимости испытывать отвращение к издевательской библиотеке. Mocha просто выполняет метапрограммирование за вас (т. Е. Методы переопределения и т. д.), О которых вы просите делать вручную.

Brian Phillips 16.09.2008 17:46

@BrianPhillips Как вы проверяете, что заглушенные методы были вызваны

Ankit Dhingra 18.09.2013 18:14

@AnkitDhingra Mocha поддерживает более детальные ожидания. если вы используете метод «ожидает» вместо «заглушек», то после запуска теста он выдаст ошибку, если фиктивный метод не был вызван.

Kevin 06.10.2014 05:51

В случае, который вы описали, я бы предположил, что то, что вы делаете, кажется нормальным. Я знаю, что эту технику пропагандировал Джеймс Мид (автор Mocha). Нет необходимости заниматься метапрограммированием только ради этого. Вот что Джеймс сказал об этом (и длинный список других техник, которые вы можете попробовать)

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

# lib/real_thing.rb
class RealThing
  def initialize a, b, c
    # ...
  end
end

# test/test_real_thing.rb
class TestRealThing < MiniTest::Unit::TestCase

  class Fake < RealThing; end

  def test_real_thing_initializer
    fake = mock()
    Fake.expects(:new).with(1, 2, 3).returns(fake)
    assert_equal fake, Fake.new(1, 2, 3)
  end

end

Другие вопросы по теме