我有两个课程AnotherClass
和class 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" />
?
答案 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)