【问题标题】:Mock system call in rubyruby 中的模拟系统调用
【发布时间】:2009-12-22 21:11:09
【问题描述】:

知道模拟 %[] 的方法吗?我正在为进行一些系统调用的代码编写测试,例如:

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

并希望在测试此方法时避免实际执行系统调用。理想情况下,我想模拟 %x[..] 并断言正确的 shell 命令被传递给它。

【问题讨论】:

    标签: ruby unit-testing mocking


    【解决方案1】:

    %x{…} 是 Ruby 内置语法,它实际上会调用内核方法 Backtick (`)。因此,您可以重新定义该方法。由于反引号方法返回在子 shell 中运行 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
      

      这是因为每个对象都从 Kernel 对象继承了诸如 system 和 ` 之类的方法。

      【讨论】:

      • 使用should_receive 代替expects
      • 不适用于当前版本。 Minitest::UnexpectedError: NoMethodError: Test:Module 的未定义方法“any_instance”;但是,如果我在对象上调用它,它会起作用。
      • 是的,陷阱是应该在进行系统调用的类上调用expects(:`),而不是在Kernel上。
      • Velizar 也一样,感谢您的评论。补充说我正在使用带有 Rails 3.2.22.1 的 Ruby 2.1.5。
      【解决方案3】:

      恐怕我不知道模拟模块的方法。至少对于 Mocha,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】:

        将其记录到文本文件或将其输出到控制台怎么样?

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

        【讨论】:

          【解决方案5】:

          你不能用一个在获取命令时返回 true 的方法来覆盖函数吗?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-02-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-10-11
            • 1970-01-01
            • 2019-01-05
            相关资源
            最近更新 更多