【问题标题】:Unable to call Ruby mixin instance method from RSpec无法从 RSpec 调用 Ruby mixin 实例方法
【发布时间】:2016-10-14 21:55:31
【问题描述】:

目标:

我想在名为 Debug 的 mixin(模块)的实例方法上运行基本的 RSpec 单元测试。以下是 Debug mixin 的文件内容:

混合文件:./mixins/debug.rb

module Debug
  public
    def class_info?
      "#{self.class.name}"
    end
end

验证可从 RSpec 访问的 Debug mixin 实例方法:

当我运行irb 并使用命令require_relative './mixins/debug.rb'include Debug 包含Debug mixin,然后调用Debug.class_info? 它成功返回"Module"

那么如果我用下面的 RSpec 单元测试运行rspec 以确认 RSpec 上下文可以访问 mixin 的实例方法,则测试成功通过:

RSpec 单元测试设置 #1:./spec/mixins/debug_spec.rb

require_relative '../../mixins/debug.rb'

RSpec.describe Debug, "#class_info?" do
  include Debug

  before(:each) do
    @class_info_instance_method = Debug.instance_methods[0].to_s
  end

  context "with mixins" do
    it "has class info instance method" do
      expect(@class_info_instance_method).to eq "class_info?"
    end
  end
end

从 RSpec 调用 Debug mixin 实例方法时出现问题:

最后,我将 RSpec 单元测试更改为如下,因此它实际上调用了 Debug mixin 的 class_info? 实例方法:

RSpec 单元测试设置 #2:./spec/mixins/debug_spec.rb

require_relative '../../mixins/debug.rb'

RSpec.describe Debug, "#class_info?" do
  include Debug

  before(:each) do
    @class_info = Debug.class_info?
  end

  context "with mixins" do
    it "shows class info" do
      expect(@class_info).to eq "Module"
    end
  end
end

但是现在当我从命令行运行 rspec 时,为什么它会返回以下错误? (注意:即使在之前的 RSpec 单元测试设置 #1 中完全相似,我检查过我可以成功访问这个 Debug mixin 实例方法)

1) Debug#class_info? with mixins shows class info
   Failure/Error: @class_info = Debug.class_info?

   NoMethodError:
     undefined method `class_info?' for Debug:Module

注意:我已经在我的RubyTest GitHub repo 中分享了上面的代码。

设置和参考:

我的系统:

  • Ruby:ruby 2.3.0p0 (ruby -v)
  • RSpec:3.5.4 (rspec -v)

参考资料:

  • Ruby 编程一书中的 Mixins 章节中的应用示例

【问题讨论】:

    标签: ruby unit-testing rspec mixins rspec3


    【解决方案1】:

    当您包含一个模块时,这些方法将成为所包含类中的实例方法。 Debug.class_info? 不起作用,因为没有类方法 class_info?。我也不确定您在测试中包含模块的方式是最好的方式。像这样的东西有用吗?

    require_relative '../../mixins/debug.rb'
    
    class TestClass
      include Debug
    end
    
    RSpec.describe Debug, "#class_info?" do
    
      let(:test_instance) { TestClass.new }
    
      context "with mixins" do
        it "shows class info" do
          expect(test_instance.class_info?).to eq "TestClass"
        end
      end
    
    end
    

    【讨论】:

    • 我通过将class_info? 更改为self.class_info? 来解决我原来的问题。但在您的示例中,test_instance.class_info? 调用超类 Debug 模块的实例方法 class_info?。所以我用两种方法更新了Debug模块:def class_info?; Debug.class_info?; enddef self.class_info?; "#{self.class.name}"; end。为了让您的测试返回“TestClass”而不是“Module”,我为 TestClass 中的class_info? 实例方法添加了一个覆盖(即def class_info?; "#{self.class.name}" end),以防止它调用超类的实例方法
    猜你喜欢
    • 2013-05-28
    • 2011-02-01
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多