GoatsWearHats GoatsWearHats - 3 years ago 133
Ruby Question

What is 'valid?' in RSpec? Where can I look at it?

I've attempted to create a model, which needs to pass a series of validation tests in RSpec. However, I constantly get the error

expected #<Surveyor::Answer:0x0055db58e29260 @question=#<Double Surveyor::Question>, @value=5> to respond to `valid?`

My understanding (from here) was that 'valid?' checks that no errors were added to the model. I can't find any errors, however the message above persists.

This is my model

module Surveyor
class Answer
attr_accessor :question, :value

def initialize(params)
@question = params.fetch(:question)
@value = params.fetch(:value)

And the class Question

module Surveyor
class Question
attr_accessor :title, :type

def initialize(params)
@title = params.fetch(:title, nil)
@type = params.fetch(:type)

And this is the test I am attempting to pass

RSpec.describe Surveyor::Answer, '03: Answer validations' do

let(:question) { double(Surveyor::Question, type: 'rating') }

context "question validation" do
context "when the answer has a question" do
subject { described_class.new(question: question, value: 5) }
it { should be_valid }

Is my understanding of 'valid?' correct? Am I able to look at 'valid?' and perhaps see where I'm going wrong?

Answer Source

RSpec doesn't actually have a matcher called be_valid, instead it has some dynamic predicate matchers:

For any predicate method, RSpec gives you a corresponding matcher. Simply prefix the method with be_ and remove the question mark. Examples:

expect(7).not_to be_zero       # calls 7.zero?
expect([]).to be_empty         # calls [].empty?
expect(x).to be_multiple_of(3) # calls x.multiple_of?(3)

so by calling it { should be_valid }, your subject has to respond to a valid? method. If you're testing an ActiveRecord model, those have a valid? method, but your model does not. So, if you want to test that your Answer is valid, you need to decide "what is a valid answer?" and write a method that checks for those conditions. If you want an API similar to Rails model, you might be interested in using ActiveModel::Validations

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download