【问题标题】:How to test a class method that modifies an attribute of another class in a containerised way rspec如何测试以容器化方式修改另一个类的属性的类方法rspec
【发布时间】:2017-02-08 09:24:41
【问题描述】:

我有一个问题困扰了我好几个小时,但无论是我还是我问过的任何人都无法找到合适的答案。

本质上,我正在编写一个方法,允许我编辑另一个方法的实例变量。我有多种方法可以做到这一点,但是我的问题是为此方法编写测试。我尝试了许多不同的 double 类型,但是由于它们是不可变的并且不存储状态,所以我没有设法让它工作。

这是 working 变量被更改的类:

class MyClass
  attr_writer :working

  def working?
    @working
  end
end

这是改变它的类和方法:

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

(实际的类要大得多,但我只包含了所讨论方法的通用版本。如果有帮助,我可以将所有特定代码放在一个要点中)

所以我需要一种方法来测试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

非常感谢您的帮助!如果某些格式/信息有点混乱,我深表歉意,我对整个 stackoverflow 还是很陌生!

【问题讨论】:

    标签: ruby rspec tdd bdd


    【解决方案1】:

    我认为问题是have_received(working = true),应该是have_received(:working=).with(true)

    编辑:

    have_received使用示例


    这对我有用

    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
    

    【讨论】:

    • 哇,谢谢!那么这只是我使用 spy 语法的错误,还是我尝试的方法不同?
    • @LMCMLJ 是的,我认为这只是使用错误语法的情况。我在答案中添加了几个链接,展示了have_received 的用法
    【解决方案2】:

    如果您只想避免存根,可以使用 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
    

    【讨论】:

      猜你喜欢
      • 2016-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-12
      • 1970-01-01
      • 2017-04-20
      相关资源
      最近更新 更多