0

I'm writing model tests with RSpec for a Cookbook model. Each user has_many cookbooks, and each cookbook belongs_to a user. To make sure that a Cookbook could not be created without a user, I wrote the following test:

it "is invalid without a user" do
  expect(FactoryGirl.build(:cookbook, user: nil)).to be_invalid
end

However, when running rspec, I get the following output:

1) Cookbook is invalid without a user
   Failure/Error: expect(FactoryGirl.build(:cookbook, user: nil)).to be_invalid
   NoMethodError:
     undefined method `cookbooks' for nil:NilClass

So, then, to test for an error being raised, I made the test like this:

it "is invalid without a user" do
  expect{FactoryGirl.build(:cookbook, user: nil)}.to raise_error(NoMethodError)
end

However, that test also fails with the following output:

1) Cookbook is invalid without a user
   Failure/Error: expect{FactoryGirl.build(:cookbook, user: nil)}.to raise_error(NoMethodError)
     expected NoMethodError but nothing was raised

If it means anything, here is the factory for the cookbook:

require 'faker'

FactoryGirl.define do
  factory :cookbook do |f|
    f.title "#{Faker::Name.first_name}'s recipes"
    f.description "#{Faker::Name.last_name}'s favorite recipes."
    f.user 1
  end
end

How should I go about writing the model test so that it makes sure a user is required when creating a Cookbook?

1
  • Please, post your Cookbook class Commented Apr 22, 2016 at 0:35

1 Answer 1

3

Within your model you may have some validation or before callback that calls bookshelves on User model. When you call be_invalid on your test, RSpec calls valid? on the object built through FactoryGirl. The object runs the validations and the error is raised since it tries to call bookshelves on a nil object (user).

When you test for error raising, it doesn't happen because valid? wasn't called on the object. Thus your test will raise the error if you do this way:

it "is invalid without a user" do
  expect{FactoryGirl.build(:cookbook, user: nil).valid?}.to raise_error(NoMethodError)
end

However I don't recommend you to only make that change on your test to make it pass. You should go to your model and check whether user is present before calling bookshelves on it. If you don't do so, your app will break whenever you try to create a Cookbook without a user.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.