在Rspec中定义类

lee*_*our 3 ruby rspec ruby-on-rails rspec2 rspec-rails

我想测试一个模块包含在一个类中.我正在尝试在RSpec中定义一个新类:

describe Statusable do
  let(:test_class) do
    class ModelIncludingStatusable < ActiveRecord::Base
      include Statusable
      statuses published: "????????????", draft: "????????"
    end
  end

  describe '#statuses' do
    it 'sets STATUSES for a model' do
      test_class::STATUSES.should == ["????????????", "????????"]
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

TypeError:
       [ActiveModel::Validations::InclusionValidator] is not a class/module
Run Code Online (Sandbox Code Playgroud)

这可能是因为Statusable我有:

validates_inclusion_of  :status, :in => statuses,
            :message => "{{value}} ?????? ???? ????? ??: #{statuses.join ','}"
Run Code Online (Sandbox Code Playgroud)

但如果我发表评论,我会得到:

TypeError:
       ["????????????", "????????"] is not a class/module
Run Code Online (Sandbox Code Playgroud)

也许新的类定义不是最好的选择,那我该怎么办?即使不是,我如何在RSpec中定义一个类?我该如何解决这个错误?

Bil*_*han 17

不要在测试中定义新常量,否则会污染其他测试.相反,使用stub_const.

此外,这是Statusable模块的单元测试.如果ActiveRecord模型不是必需的,最好不要使用它.

您也可以使用class_eval以避免实际打开此类(无论是否伪造)

describe Statusable do
  before do
    stub_const 'Foo', Class.new
    Foo.class_eval{ include Statusable }
    Foo.class_eval{ statuses published: "foo", draft: "bar"}
  end

  context '#statuses' do
    it 'sets STATUSES for a model' do
      FOO::STATUSES.should == ["foo", "bar"]
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

虽然我复制了你的断言,但我建议不要在STATUS包含这个模块的类/模块(Foo)中插入一个常量.相反,类方法会更好

expect(Foo.status).to eq(["foo", "bar"])
Run Code Online (Sandbox Code Playgroud)