Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 + Rspec: Testing that a model has an attribute?

Is there a way to test that a model has a specific attribute? Right now I am just using respond_to like this:

describe Category do
  it { should respond_to(:title) }
  ...
end

to test that the Category model has an attribute, but that only really tests that there is an instance method called title. However, I can see how in some situations they would behave synonymously.

like image 221
bigpotato Avatar asked Dec 10 '13 21:12

bigpotato


People also ask

How do I run a specific test in RSpec?

Running tests by their file or directory names is the most familiar way to run tests with RSpec. RSpec can take a file name or directory name and run the file or the contents of the directory. So you can do: rspec spec/jobs to run the tests found in the jobs directory.

Is RSpec used for unit testing?

RSpec is a unit test framework for the Ruby programming language. RSpec is different than traditional xUnit frameworks like JUnit because RSpec is a Behavior driven development tool.

What is let in RSpec?

let generates a method whose return value is memoized after the first call. This is known as lazy loading because the value is not loaded into memory until the method is called. Here is an example of how let is used within an RSpec test. let will generate a method called thing which returns a new instance of Thing .


2 Answers

You can test for the presence of an attribute in an instance of the model with the following:

it "should include the :title attribute" do
  expect(subject.attributes).to include(:title)
end

or using the its method (in a separate gem as of RSpec 3.0):

its(:attributes) { should include("title") }

See the related How do you discover model attributes in Rails. (Nod to @Edmund for correcting the its example.)

like image 101
Peter Alfvin Avatar answered Nov 09 '22 17:11

Peter Alfvin


This is a bit of a necropost, but I wrote a custom rspec matcher that should make testing the presence of a model attribute easier:

RSpec::Matchers.define :have_attribute do |attribute|
  chain :with_value do |value|
    @value = value
  end

  match do |model|
    r = model.attributes.include? attribute.to_s
    r &&= model.attributes[attribute] == @value if @value
    r
  end

  failure_message do |model|
    msg = "Expected #{model.inspect} to have attribute #{attribute}"
    msg += " with value #{@value}" if @value
    msg
  end

  failure_message_when_negated do |model|
    msg = "Expected #{model.inspect} to not have attribute #{attribute}"
    msg += " with value #{@value}" if @value
    msg
  end
end
like image 42
glittershark Avatar answered Nov 09 '22 18:11

glittershark