如何测试以容器化方式 rspec 修改另一个 class 属性的 class 方法
How to test a class method that modifies an attribute of another class in a containerised way rspec
我有一个问题已经困扰我好几个小时了,我和我问过的任何人都无法给出合适的答案。
本质上,我正在编写一个允许我编辑另一个方法的实例变量的方法。我有多种方法可以做到这一点,但我的问题是为此方法编写测试。我已经尝试了许多不同的双精度类型,但是由于它们是不可变的并且不存储状态,所以我没有找到一种方法来使其工作。
这里是 class,其 working
变量被更改:
class MyClass
attr_writer :working
def working?
@working
end
end
这里是 class 和改变它的方法:
class OtherClass
def makes_work
@ary_of_instances_of_MyClass_to_fix.map do |x|
x.working = true
@ary_of_fixed_objects << x
end
end
end
(实际的 class 要大得多,但我只包含了所讨论方法的通用版本。如果有帮助,我可以将所有具体代码放在要点中)
所以我需要一种方法来测试 makes_work
实际上接受要更改的对象数组,更改它们并将它们附加到 array_of_fixed_objects
。在不需要 MyClass 的情况下以容器化方式测试它的最佳方法是什么?
我最后一次尝试是使用间谍来查看在我的虚拟实例上调用了哪些方法,但是失败了一系列,这取决于我做了什么。这是我最近写的测试:
describe '#make_work' do
it 'returns array of working instances' do
test_obj = spy('test_obj')
subject.ary_of_instances_of_MyClass_to_fix = [test_obj]
subject.makes_work
expect(test_obj).to have_received(working = true)
end
end
当前抛出错误:
undefined method to_sym for true:TrueClass
非常感谢您的帮助!如果某些格式/信息有点混乱,我深表歉意,我对整个 Whosebug 还是很陌生!
我觉得问题是have_received(working = true)
,应该是have_received(:working=).with(true)
编辑:
使用示例 have_received
- https://github.com/rspec/rspec-mocks#test-spies
- https://relishapp.com/rspec/rspec-mocks/v/3-5/docs/setting-constraints/matching-arguments
这对我有用
class MyClass
attr_writer :working
def working?
@working
end
end
class OtherClass
attr_writer :ary_of_instances_of_MyClass_to_fix
def initialize
@ary_of_fixed_objects = []
end
def makes_work
@ary_of_instances_of_MyClass_to_fix.map do |x|
x.working = true
@ary_of_fixed_objects << x
end
end
end
describe '#make_work' do
subject { OtherClass.new }
it 'returns array of working instances' do
test_obj = spy('test_obj')
subject.ary_of_instances_of_MyClass_to_fix = [test_obj]
subject.makes_work
expect(test_obj).to have_received(:working=).with(true)
end
end
如果您只想避免存根,可以使用 OpenStruct 的实例而不是双精度实例:
class OtherClass
attr_writer :ary_of_instances_of_MyClass_to_fix
def initialize
@ary_of_instances_of_MyClass_to_fix, @ary_of_fixed_objects = [], []
end
def makes_work
@ary_of_instances_of_MyClass_to_fix.map do |x|
x.working = true
@ary_of_fixed_objects << x
end
@ary_of_fixed_objects
end
end
require 'ostruct'
RSpec.describe "#makes_work" do
describe "given an array" do
let(:array) { [OpenStruct.new(working: nil)] }
subject { OtherClass.new }
before do
subject.ary_of_instances_of_MyClass_to_fix = array
end
it "sets the 'working' attribute for each element" do
expect(array.map(&:working)).to eq [nil]
subject.makes_work
expect(array.map(&:working)).to eq [true]
end
end
end
我有一个问题已经困扰我好几个小时了,我和我问过的任何人都无法给出合适的答案。
本质上,我正在编写一个允许我编辑另一个方法的实例变量的方法。我有多种方法可以做到这一点,但我的问题是为此方法编写测试。我已经尝试了许多不同的双精度类型,但是由于它们是不可变的并且不存储状态,所以我没有找到一种方法来使其工作。
这里是 class,其 working
变量被更改:
class MyClass
attr_writer :working
def working?
@working
end
end
这里是 class 和改变它的方法:
class OtherClass
def makes_work
@ary_of_instances_of_MyClass_to_fix.map do |x|
x.working = true
@ary_of_fixed_objects << x
end
end
end
(实际的 class 要大得多,但我只包含了所讨论方法的通用版本。如果有帮助,我可以将所有具体代码放在要点中)
所以我需要一种方法来测试 makes_work
实际上接受要更改的对象数组,更改它们并将它们附加到 array_of_fixed_objects
。在不需要 MyClass 的情况下以容器化方式测试它的最佳方法是什么?
我最后一次尝试是使用间谍来查看在我的虚拟实例上调用了哪些方法,但是失败了一系列,这取决于我做了什么。这是我最近写的测试:
describe '#make_work' do
it 'returns array of working instances' do
test_obj = spy('test_obj')
subject.ary_of_instances_of_MyClass_to_fix = [test_obj]
subject.makes_work
expect(test_obj).to have_received(working = true)
end
end
当前抛出错误:
undefined method to_sym for true:TrueClass
非常感谢您的帮助!如果某些格式/信息有点混乱,我深表歉意,我对整个 Whosebug 还是很陌生!
我觉得问题是have_received(working = true)
,应该是have_received(:working=).with(true)
编辑:
使用示例 have_received
- https://github.com/rspec/rspec-mocks#test-spies
- https://relishapp.com/rspec/rspec-mocks/v/3-5/docs/setting-constraints/matching-arguments
这对我有用
class MyClass
attr_writer :working
def working?
@working
end
end
class OtherClass
attr_writer :ary_of_instances_of_MyClass_to_fix
def initialize
@ary_of_fixed_objects = []
end
def makes_work
@ary_of_instances_of_MyClass_to_fix.map do |x|
x.working = true
@ary_of_fixed_objects << x
end
end
end
describe '#make_work' do
subject { OtherClass.new }
it 'returns array of working instances' do
test_obj = spy('test_obj')
subject.ary_of_instances_of_MyClass_to_fix = [test_obj]
subject.makes_work
expect(test_obj).to have_received(:working=).with(true)
end
end
如果您只想避免存根,可以使用 OpenStruct 的实例而不是双精度实例:
class OtherClass
attr_writer :ary_of_instances_of_MyClass_to_fix
def initialize
@ary_of_instances_of_MyClass_to_fix, @ary_of_fixed_objects = [], []
end
def makes_work
@ary_of_instances_of_MyClass_to_fix.map do |x|
x.working = true
@ary_of_fixed_objects << x
end
@ary_of_fixed_objects
end
end
require 'ostruct'
RSpec.describe "#makes_work" do
describe "given an array" do
let(:array) { [OpenStruct.new(working: nil)] }
subject { OtherClass.new }
before do
subject.ary_of_instances_of_MyClass_to_fix = array
end
it "sets the 'working' attribute for each element" do
expect(array.map(&:working)).to eq [nil]
subject.makes_work
expect(array.map(&:working)).to eq [true]
end
end
end