Макет системного вызова в рубине

Знать способ издеваться над% []? Я пишу тесты для кода, который выполняет несколько системных вызовов, например:

def log(file)
  %x[git log #{file}]
end

и хотел бы избежать фактического выполнения системных вызовов при тестировании этого метода. В идеале я хотел бы высмеять% x [..] и утверждать, что правильная команда оболочки передается ему.

Ответ 1

%x{…} - это встроенный синтаксис Ruby, который на самом деле вызовет метод Kernel Backtick (`). Таким образом, вы можете переопределить этот метод. Когда метод backtick возвращает стандартный вывод работы cmd в подоболочке, ваш переопределенный метод должен возвращать нечто похожее на это, например строку.

module Kernel
    def `(cmd)
        "call #{cmd}"
    end
end

puts %x(ls)
puts `ls`
# output
# call ls
# call ls

Ответ 2

Используя Mocha, если вы хотите посмеяться над следующим классом:

class Test
  def method_under_test
    system "echo 'Hello World!"
    `ls -l`
  end
end

ваш тест будет выглядеть примерно так:

def test_method_under_test
  Test.any_instance.expects(:system).with("echo 'Hello World!'").returns('Hello World!').once
  Test.any_instance.expects(:`).with("ls -l").once
end

Это работает, потому что каждый объект наследует такие методы, как system и `от объекта Kernel.

Ответ 3

Я не знаю, как насмехаться над модулем, я боюсь. С моккой, по крайней мере, Kernel.expects не помогает. Вы всегда можете обернуть вызов в классе и высмеять это, что-то вроде этого:

require 'test/unit'
require 'mocha'

class SystemCaller
  def self.call(cmd)
    system cmd
  end
end

class TestMockingSystem < Test::Unit::TestCase
  def test_mocked_out_system_call
    SystemCaller.expects(:call).with('dir')
    SystemCaller.call "dir"
  end
end

который дает мне то, на что я надеюсь:

Started
.
Finished in 0.0 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

Ответ 4

Не можете ли вы просто переустановить функцию с помощью метода, который возвращает true, когда получает команду?

Ответ 5

Как записывать его в текстовый файл или выводить его на консоль?

def log(file)
  puts "git log #{file}"
end