【问题标题】:How do I stub a method of an instance only if a specific instance variable has a value?仅当特定实例变量具有值时,如何存根实例的方法?
【发布时间】:2023-03-05 09:17:01
【问题描述】:

我有一个对象MyObject

class MyObject

  def initialize(options = {})
    @stat_to_load = options[:stat_to_load] || 'test'
  end

  def results
   []
  end
end

我只想在stat_to_load = "times" 时存根results 方法。我怎样才能做到这一点?我试过了:

MyObject.any_instance.stubs(:initialize).with({
  :stat_to_load => "times"
}).stubs(:results).returns(["klala"])

但它不起作用。有什么想法吗?

【问题讨论】:

  • 我可以看到问题中resultresults 不匹配。可能不是您的答案,但值得修复吗?
  • Oups,复制/粘贴错误
  • 我什至不知道这是否可能,但可能正确的解决方案是注入对象或类,然后你对它有更多的控制权。很难说/给出例子而不看这段代码是如何使用的。
  • 如果你有我的类 MyObject.我想为 Rails 测试存根。

标签: ruby-on-rails ruby testing stub ruby-mocha


【解决方案1】:

所以,我认为可能有一种更简单的方法来测试您要测试的内容,但如果没有更多上下文,我不知道该推荐什么。但是,这里有一些概念验证代码,表明您想做的事情是可以完成的:

describe "test" do
  class TestClass
    attr_accessor :opts
    def initialize(opts={})
      @opts = opts
    end

    def bar
      []
    end
  end
  let!(:stubbed) do
    TestClass.new(args).tap{|obj| obj.stub(:bar).and_return("bar")}
  end
  let!(:unstubbed) { TestClass.new(args) }

  before :each do
    TestClass.stub(:new) do |args|
      case args
      when { :foo => "foo" }
        stubbed
      else
        unstubbed
      end
    end
  end

  subject { TestClass.new(args) }

  context "special arguments" do
    let(:args) { { :foo => "foo" } }
    its(:bar) { should eq "bar" }
    its(:opts) { should eq({ :foo => "foo" }) }
  end

  context "no special arguments" do
    let(:args) { { :baz => "baz" } }
    its(:bar) { should eq [] }
    its(:opts) { should eq({ :baz => "baz" }) }
  end

end

test
  special arguments
    bar
      should == bar
    opts
      should == {:foo=>"foo"}
  no special arguments
    bar
      should == []
    opts
      should == {:baz=>"baz"}

Finished in 0.01117 seconds
4 examples, 0 failures

但是,我在这里大量使用了特殊的主题/让上下文块。有关该主题的更多信息,请参阅http://benscheirman.com/2011/05/dry-up-your-rspec-files-with-subject-let-blocks/

【讨论】:

  • 此答案适用于 RSpec 而不是 mocha
【解决方案2】:

在下面尝试,这应该可以按预期工作:

在这里,基本上我们实际上是在创建 new instance 存根,并在返回的实例的 results 方法上存根。

options = {:stat_to_load =>  "times"}
MyObject.stubs(:new).with(options)
                    .returns(MyObject.new(options).stubs(:results).return(["klala"]))

【讨论】:

    【解决方案3】:

    您可以在测试中使用普通的旧 Ruby 来实现这一点。

    MyObject.class_eval do
      alias_method :original_results, :results
      define_method(:results?) do
        if stats_to_load == "times"
          ["klala"]
        else
          original_results
        end
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 2020-08-13
      • 2018-05-31
      • 2018-10-01
      相关资源
      最近更新 更多