Насмешливые конструкторы в Ruby - PullRequest
3 голосов
/ 16 сентября 2008

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

def initialize(file_class=File)

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

@file_class.open(filename)

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

Ответы [ 3 ]

11 голосов
/ 16 сентября 2008

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)

1 голос
/ 21 июня 2013

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

# 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
1 голос
/ 16 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...