2009-10-27 16 views
15

¿Conoce una forma de burlarse% []? Estoy escribiendo pruebas de código que hace un par de llamadas al sistema, por ejemplo:Llamada falsa del sistema en ruby ​​

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

y me gustaría evitar ejecutar realmente las llamadas al sistema, mientras que las pruebas de este método. Idealmente, me gustaría simular% x [..] y afirmar que se le pasa el comando de shell correcto.

Respuesta

17

%x{…} es Rubí incorporado en la sintaxis que realmente llamar al método Kernel Backtick (`). Entonces puedes redefinir ese método. Como el método backtick devuelve el resultado estándar de ejecutar cmd en una subshell, su método redefinido debe devolver algo similar a eso, por ejemplo, una cadena.

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

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

¿No puede simplemente anular la función con un método que devuelve verdadero cuando obtiene el comando?

0

¿Qué le parece registrarlo en un archivo de texto o enviarlo a su consola?

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

No sé de una manera de burlarse de un módulo, me temo. Con Mocha al menos, Kernel.expects no ayuda. Usted podría envuelva siempre la vocación en una clase y se burlan de eso, algo como esto:

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 

que me da lo que yo espero para:

Started 
. 
Finished in 0.0 seconds. 

1 tests, 1 assertions, 0 failures, 0 errors 
12

Usando Mocha, si quieres maqueta a la clase siguiente:

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

su prueba sería algo como:

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 

Esto funciona porque cada objeto hereda métodos como system y `del objeto Kernel.

+0

al menos la versión: 'funciona también con rspec 2 mocks –

+0

Usando' should_receive' en lugar de 'espera' –

+1

No funciona con la versión actual. Minitest :: UnexpectedError: NoMethodError: método indefinido 'any_instance 'for Test: Module; Sin embargo, funcionó si lo llamé sobre el objeto. –

Cuestiones relacionadas