【问题标题】:Why is my test double not expecting the command I allowed?为什么我的测试替身不期待我允许的命令?
【发布时间】:2014-02-08 11:31:16
【问题描述】:

我有一些代码可以对 Linux 操作系统进行 shellout 调用,它将运行特定于发行版的命令。我试图确保测试可以在任何系统上运行,所以我对Mixlib::ShellOut 调用使用了测试替身。这是复制我的问题的简化版本:

require 'mixlib/shellout'
class SelinuxCommand
  def run
    runner = Mixlib::ShellOut.new('getenforce')
    runner.run_command
  end
end

我的测试存根Mixlib:ShellOut.new 返回一个测试替身,然后说:run_command 应该返回字符串'Enforcing'

require 'rspec'
require_relative 'selinuxcommand'
describe SelinuxCommand do
  it 'gets the Selinux enforcing level' do
    command = SelinuxCommand.new
    Mixlib::ShellOut.stub(:new).and_return(double)
    allow(double).to receive(:run_command).and_return('Enforcing')
    expect command.run.to eql 'Enforcing'
  end
end

但是,当我运行测试时,我看到:

$ rspec -fd selinuxcommand_spec.rb

SelinuxCommand   gets the Selinux enforcing level (FAILED - 1)

Failures:

  1) SelinuxCommand gets the Selinux enforcing level
     Failure/Error: expect command.run.to eql 'Enforcing'
       Double received unexpected message :run_command with (no args)
     # ./selinuxcommand.rb:5:in `run'
     # ./selinuxcommand_spec.rb:9:in `block (2 levels) in <top (required)>'

Finished in 0.00197 seconds 1 example, 1 failure

Failed examples:

rspec ./selinuxcommand_spec.rb:5 # SelinuxCommand gets the Selinux enforcing level

我不明白为什么当我明确地将它设置为期望时,双重不期望:run_command。我错过了什么?

【问题讨论】:

    标签: ruby rspec mocking


    【解决方案1】:

    只是因为每次调用double都会得到一个不同的对象,所以允许接收run_command方法的对象与被存根的new返回的对象不是同一个对象。你可以这样修复它:

    it 'Gets the Selinux enforcing level' do
      runner = double
      Mixlib::ShellOut.stub(:new).and_return(runner)
    
      expect(runner).to receive(:run_command).and_return('Enforcing')
      expect(subject.run).to eq('Enforcing')
    end
    

    【讨论】:

    • 这行得通!谢谢。我忘记了 double 是一种返回新双精度的方法,而不仅仅是同一个实例。 +1 还提醒我使用 subject 而不是实例化新实例。
    【解决方案2】:

    现在无法检查,但在我看来您需要存根 :initialize 方法 - 而不是 :new

    试试这个变种:

    Mixlib::ShellOut.stub(:initialize).and_return(double)
    

    【讨论】:

    • 对显式构造函数进行存根有两个影响:(1) 警告:删除 `initialize' 可能会导致严重问题;(2) 失败:Mixlib 尝试调用不存在的 getenforce,因此给出没有这样的文件或目录错误。这告诉我们,即使 :new 是 :initialize 的别名,存根似乎只对显式调用的方法生效。
    猜你喜欢
    • 2016-06-09
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 2022-11-18
    相关资源
    最近更新 更多