如何在rspec中模拟实例变量

时间:2016-05-16 06:41:40

标签: rspec

我有两个课程AnotherClassclass OneClass def initialize(*args) @another_member = AnotherClass.new() end def my_method() if @another_member.another_method1() then @another_member.another_method2() end @another_member.another_method3() end end

OneClass

我要为@another_member写单位。 我如何模仿<EditText android:id="@+id/subject_edt" style="@android:style/TextAppearance.Medium" android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginLeft="15dp" android:inputType="textImeMultiLine" android:layout_marginRight="15dp" android:background="@drawable/edt_bg" android:maxLines="5" />

3 个答案:

答案 0 :(得分:3)

您无法模拟实例变量。你只能模拟方法。一种选择是在OneClass中定义一个包装another_member的方法,并模拟该方法。

class OneClass
  def initialize(*args)
  end

  def my_method()
    if another_member.another_method1() then
      another_member.another_method2()
    end
    another_member.another_method3()
  end

  private

  def another_member
    @another_member ||= AnotherClass.new()
  end

end

但是,您没有必要,有更好的方法来编写和测试您的代码。在这种情况下,更好的模拟方法是使用名为Dependency Injection的模式。

您将依赖项传递给初始值设定项。

class OneClass
  def initialize(another: AnotherClass, whatever:, somethingelse:)
    @another_member = another.new()
  end

  def my_method()
    if @another_member.another_method1() then
      @another_member.another_method2()
    end
    @another_member.another_method3()
  end
end

(注意我使用了关键字参数,但你没有。你也可以使用标准的args方法。)

然后,在测试套件中,您只需提供测试对象。<​​/ p>

let(:test_another) {
  Class.new do
    def another_method1
      :foo
    end
    def another_method2
      :bar
    end
    def another_method3
      :baz
    end
  end
}

it "does something" do
  subject = OneClass.new(another: test_another)
  # ...
end

这种方法有几个优点。特别是,您可以避免在测试中使用mock,并且确实可以单独测试对象。<​​/ p>

答案 1 :(得分:2)

凭借安东尼的想法,我让它发挥作用。

describe OneClass do
  before(:each) { @one_object = OneClass.new }

  describe 'my_method' do
    it 'should work' do
      mock_member = double
      allow(mock_member).to receive(:another_method1).and_return(true)
      @one_object.instance_variable_set(:@another_member, mock_member)

      @one_object.my_method()

      expect(mock_member).to have_received(:another_method1)
    end
  end
end

答案 2 :(得分:0)

您可以通过存根@another_member来间接模仿AnotherClass.new

another_member_double = double()
allow(AnotherClass).to receive(:new).and_return(another_member_double)

expect(another_member_double).to receive(:another_method1).and_return(somevalue)