Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define class in Rspec

I want to test an inclusion of a module into a class. I am trying define a new class in 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

And I get an error:

TypeError:
       [ActiveModel::Validations::InclusionValidator] is not a class/module

This is probably because in Statusable I have:

validates_inclusion_of  :status, :in => statuses,
            :message => "{{value}} должен быть одним из: #{statuses.join ','}"

But if I comment it out, I get:

TypeError:
       ["опубликовано", "черновик"] is not a class/module

Maybe new class definition isn't the best option, what do I do then? And even if it's not, how can I define a class in RSpec? And how do I fix this error?

like image 449
leemour Avatar asked Nov 29 '22 07:11

leemour


1 Answers

Do not define new constant in tests otherwise it will pollute other tests. Instead, use stub_const.

Also, for this is an unit test of Statusable module. If ActiveRecord model is not a necessity, better not to use it.

You can also use class_eval to avoid not opening this class(no matter fake or not) actually

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

Though I copied your assertion, I would suggest not to insert a constant say STATUS into the class/module(Foo) who includes this module. Instead, a class method would be better

expect(Foo.status).to eq(["foo", "bar"])
like image 175
Billy Chan Avatar answered Dec 05 '22 15:12

Billy Chan