Rspec - 测试通过类名调用模块方法的类方法

时间:2017-04-30 14:26:12

标签: ruby-on-rails ruby rspec

我想写一个rspec测试来验证一个类方法,它通过类名调用包含的模块方法。当我使用Module名称调用模块方法时,它可以正常工作,但在按类名调用时会抛出NoMethodError。

module Test
  def self.module_mtd
    p "test"
  end
end

class Burger 
  include Test

  attr_reader :options

  def initialize(options={})
    @options = options
  end

  def apply_ketchup
    @ketchup = @options[:ketchup]
  end

  def has_ketchup_on_it?
    Burger.module_mtd # Throws NoMethodError
    Test.module_mtd #Works fine as expected
    @ketchup
  end
end


describe Burger do
  describe "#apply_ketchup" do
    subject { burger }
    before  { burger.apply_ketchup }

    context "with ketchup" do
      let(:burger) { Burger.new(:ketchup => true) }

      it { should have_ketchup_on_it }
    end

    context "without ketchup" do
      let(:burger) { Burger.new(:ketchup => false) }

      it { should_not have_ketchup_on_it }
    end
  end
end

1 个答案:

答案 0 :(得分:1)

问题不在于测试本身,而在于你对类方法如何在Ruby中工作的理解。

module Test
  def self.module_mtd
    p "test"
  end
end

声明属于Test的方法。与模块实例方法不同,当您包含模块时,不会将其添加到类中。

要从模块声明一个类方法,您需要使用模块mixins模式来扩展单例类:

module Test
  # this is called when you include the module
  def self.included(base)
    # this adds the class methods to the class
    base.extend ClassMethods
  end

  module ClassMethods
    def foo
      puts "hello world"
    end
  end
end

module ClassMethodsfoo声明为实例方法这一事实看起来有点令人困惑,直到您意识到要扩展的单例类是" Class"的实例。

请参阅: