使用rspec测试Ruby模块

时间:2014-12-07 10:40:40

标签: ruby rspec

我很难在SO / Google上找到这个特殊情况。我有一个带有函数的模块,为了使用它们,你必须创建一个包含/扩展模块的类,具体取决于你是否需要实例方法或类方法。

module A
  def say_hello name
    "hello #{name}"
  end

  def say_bye
    "bye"
  end
end

如何使用rspec测试此模块?

我有这样的事情,我不知道应该在哪里创建课程并扩展模块。

describe A do
  class MyClass
    extend A
  end

  before(:each) { @name = "Radu" }

  describe "#say_hello" do
    it "should greet a name" do
      expect(Myclass.say_hello(@name)).to eq "hello Radu"
    end
  end
end

谢谢!

2 个答案:

答案 0 :(得分:26)

您可以在测试中创建一个匿名类:

describe A do
  let(:extended_class) { Class.new { extend A } }
  let(:including_class) { Class.new { include A } }

  it "works" do
    # do stuff with extended_class.say_hello
    # do stuff with including_class.new.say_hello
  end
end

要在实际代码中查看类似内容,我已将此策略用于testing my attr_extras lib

那就是说,includeextend是Ruby的标准功能,所以我不会测试每个模块在包含和扩展时都能正常工作 - 这通常是给定的。

如果您在测试中创建了一个命名类,就像您在问题中所做的那样,我相信该类将在测试运行期间全局存在。所以这个类会在测试套件的每次测试之间泄漏,可能会在某处造成冲突。

如果使用let创建匿名类,则只能在此特定测试中使用。没有指向它的全局常量可能与其他测试冲突。

答案 1 :(得分:0)

为了帮助未来的读者,这是我使用@ henrik-n解决方案的一个例子:

# slim_helpers.rb
module SlimHelpers

  # resourceToTitle converts strings like 'AWS::AutoScaling::AutoScalingGroup'
  # to 'Auto Scaling Group'
  def resourceToTitle(input)
    input.split('::')[-1].gsub(/([A-Z])/, ' \1').lstrip
  end

end

# slim_helpers_spec.rb
require_relative '../slim_helpers'

describe SlimHelpers do

  # extended class
  let(:ec) { Class.new { extend SlimHelpers } }

  it "converts AWS resource strings to titles" do
    out = ec.resourceToTitle('AWS::AutoScaling::AutoScalingGroup')
    expect(out).to eq 'Auto Scaling Group'
  end
end