2009-10-27 18 views
15

Conoscere un modo per simulare% []? Sto scrivendo test per il codice che fa un paio di chiamate di sistema, ad esempio:Mock system call in ruby ​​

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

e vorrei evitare di espletare effettivamente le chiamate di sistema durante la prova di questo metodo. Idealmente mi piacerebbe prendere in giro% x [..] e affermare che il comando di shell corretto è passato ad esso.

risposta

17

%x{…} rubino built-in sintassi che effettivamente chiamare il metodo Kernel Backtick (`). Quindi puoi ridefinire quel metodo. Poiché il metodo backtick restituisce l'output standard di esecuzione di cmd in una subshell, il metodo ridefinito dovrebbe restituire qualcosa di simile a quello, ad esempio, una stringa.

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

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

Non è possibile ovverride della funzione con un metodo che restituisce true quando riceve il comando?

0

Che ne dici di registrarlo in un file di testo o di inviarlo alla console?

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

Non conosco un modo per prendere in giro un modulo, temo. Almeno con Mocha, Kernel.expects non aiuta. Si potrebbe avvolgere sempre la chiamata in una classe e finto che, qualcosa di simile:

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 

che mi dà quello che mi auguro per:

Started 
. 
Finished in 0.0 seconds. 

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

Utilizzando Mocha, se si desidera finta a seguire classe:

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

il test sarebbe simile:

012.
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 

Ciò funziona perché ogni oggetto eredita metodi come system e `dall'oggetto Kernel.

+0

almeno la versione '' funziona con rspec 2 mock e –

+0

Utilizzare 'should_receive' invece di' expect' –

+1

Non funziona con la versione corrente. Minitest :: UnexpectedError: NoMethodError: metodo undefined 'any_instance 'per Test: Module; Tuttavia, ha funzionato se l'ho chiamato sull'oggetto. –