45
class TestController < AplicationController
  #....

  private

  def some_method
    unless @my_variable.nil?
      #...
      return true
    end
  end
end

我想some_method直接在控制器规范中测试:

require 'spec_helper'

describe TestController do
  it "test some_method"
    phone = Phone.new(...)
    controller.assign(:my_variable,phone) #does not work
    controller.send(:some_method).should be_true
  end
end

如何从控制器规范设置TestController实例变量?@my_variable

4

3 回答 3

71

在控制器中测试私有方法时send,我倾向于使用匿名控制器,因为不想直接调用私有方法,而是私有方法的接口(或者,在下面的测试中,有效地存根该接口)。所以,在你的情况下,也许是这样的:

require 'spec_helper'

describe TestController do
  controller do
    def test_some_method
      some_method
    end
  end

  describe "a phone test with some_method" do

    subject { controller.test_some_method }

    context "when my_variable is not nil" do
      before { controller.instance_variable_set(:@my_variable, Phone.new(...)) }
      it { should be_true }
    end

    context "when my_variable is nil" do
      before { controller.instance_variable_set(:@my_variable, nil) } 
      it { should_not be_true } # or should be_false or whatever
    end     
  end
end

在这个 StackOverflow Q&A中,关于直接测试私有方法的问题有一些很好的讨论,这让我倾向于使用匿名控制器,但你的意见可能不同。

于 2013-04-15T00:31:40.350 回答
3

instance_eval是一种相对干净的方法来实现这一点:

describe TestController do
  it "test some_method" do
    phone = Phone.new(...)
    controller.instance_eval do
      @my_variable = phone
    end
    controller.send(:some_method).should be_true
  end
end

在这种情况下,使用do...endoninstance_eval是多余的,这三行可以缩短为:

controller.instance_eval {@my_variable = phone}
于 2017-11-22T18:17:21.687 回答
2

我不认为你想从你的规范控制器访问一个实例变量,因为规范应该测试行为,但你总是可以存根私有方法。在你的情况下,它应该是这样的(在这个例子中它没有多大意义):

describe TestController do
  it "test some_method"
    phone = Phone.new(...)
    controller.stub(:some_method).and_return(true)
    controller.send(:some_method).should be_true
  end
end

如果这不是您要查找的内容,请查看:如何设置方法测试中使用的私有实例变量?

于 2013-04-15T00:05:46.880 回答