rSpec Testing Rails using Shoulda matchers

factory-bot, rspec, ruby-on-rails, shoulda, testing

Solution

It's being run on "subject", which is either explicitly defined through the `subject` method or implicitly defined by passing in a class as the argument to `describe`, in which case an instance of that class is instantiated and made the subject of the test. See https://www.relishapp.com/rspec/rspec-core/v/2-0/docs/subject/explicit-subject and https://www.relishapp.com/rspec/rspec-core/v/2-0/docs/subject/implicit-subject

As for the answer to the Update question, in your model validations for `:speed` and `:length`, you have `allow_nil: true`, which is why those two tests are failing. Part of the definition of `validates_presence_of` is that `nil` is not a settable value.

As for your latest question, I think you may be confused about the use of implicit subjects. If `should` is used by itself, it will indeed default to whatever the `subject` is, but if you include a subject yourself, as you have in this case with `name_and_park`, it won't treat that as a method of the default subject, it must have a definition within the current namespace. In your case, you would need to say `subject.name_and_park.should ...`.

On a related aside, StackOverflow is best used when you ask a specific question or related set of questions and get an answer. For a variety of reasons, it's not intended for ongoing debugging sessions. One of those reasons is that it becomes tedious tracking substantial, sequential updates of the original question and answer.

Problem

I have been starting to learn testing in my Rails app and am using rSpec and Shoulda. I have the following test which works: ``` it { should respond_to(:park_name) } ``` However, what I don't understand is, what is this being run on? Is this being run on the Model itself or an instance of the model and if it's an instance of the Model then is it automatically using my Factory Girl factory? Any simple explanations on what is actually occurring here? UPDATE: Ok, So I have this: ``` describe 'validations' do subject { FactoryGirl.build(:coaster) } it { should validate_presence_of(:name) } it { should validate_presence_of(:speed) } it { should validate_presence_of(:height) } end ``` But the tests are failing. Any ideas? Coaster.rb: ``` class Coaster < ActiveRecord::Base extend FriendlyId friendly_id :slug, use: :slugged belongs_to :park belongs_to :manufacturer attr_accessible :name, :height, :speed, :length, :inversions, :material, :lat, :lng, :park_id, :notes, :manufacturer_id, :style, :covering, :ride_style, :model, :layout, :dates_ridden, :times_ridden, :order, :on_ride_photo scope :by_name_asc, lambda { order("name ASC") } scope :made_from, lambda { |material| where("material = ?", material) } scope :wooden, lambda { made_from "wood" } scope :steel, lambda { made_from "steel" } delegate :name, :location_1, :location_2, :location_3, :location_4, to: :park, allow_nil: true, prefix: true delegate :name, :url, to: :manufacturer, prefix: true validates :name, :presence => true validates :height, allow_nil: true, numericality: {greater_than: 0} validates :speed, allow_nil: true, numericality: {greater_than: 0} validates :length, allow_nil: true, numericality: {greater_than: 0} ``` Test Results: 1) Coaster validations should require speed to be set Failure/Error: it { should validate_presence_of(:speed) } Expected errors to include "can't be blank" when speed is set to nil, got no errors # ./spec/models/coaster_spec.rb:75:in `block (3 levels) in ' 2) Coaster validations should require height to be set Failure/Error: it { should validate_presence_of(:height) } Expected errors to include "can't be blank" when height is set to nil, got no errors # ./spec/models/coaster_spec.rb:76:in `block (3 levels) in ' SIMILAR QUESTION: I have this test: ``` describe 'methods' do subject { FactoryGirl.build(:coaster) } it "should return a formatted string of coaster name at park name" do name_and_park.should eq('Nemesis at Alton Towers') end end ``` Coaster.rb: ``` def name_and_park [name, park.name].join (' at ') end ``` Error when running the test: 2) Coaster methods should return a formatted string of coaster name at park name Failure/Error: name_and_park.should eq('Nemesis at Alton Towers') NameError: undefined local variable or method `name_and_park' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_6:0x007f84f4161798> # ./spec/models/coaster_spec.rb:111:in`block (3 levels) in ' It says name_and_park cannot be called but surely that method should be being called on the instance of Coaster that is being made in the subject line? No?

Original source