简体   繁体   中英

Rails testing a model says 'Expected false to be truthy'

I am having site where users can create products upon signup and products can have checklists.

I am having a checklist table with following columns:-

id  |  product_id  | content  |  archived 

I am new to rails testing. I wrote the test below

  test 'should have content' do
    checklist = Checklist.new
    assert checklist.save
  end

and run the test with following command

ruby -I test test/models/checklist_test.rb

and test is failed with Expected false to be truthy error.

Is it because of the problem a checklist can be accessed using user.product.checklists i have to populate the data in fixtures first and call those in testing?

EDIT 1

I don't have any validations in checklist model.

class Checklist < ApplicationRecord belongs_to :product end

I added ! in test save like below

  test 'should have content' do
    checklist = Checklist.new
    assert checklist.save!
  end

and got this error

ActiveRecord::RecordInvalid: Validation failed: Product must exist

cause the table has product_id in it. I don't know how to supply data to rails test. Any help?

EDIT 2

The error is eliminated after editing like below.

class Checklist < ApplicationRecord belongs_to :product, optional: true end

However i want to test the model with product present. I don't know how to supply data to the test with fixtures as if there is no foreign key i can use Checklist.new in test.

Since it has foreign key how can i supply data to Checklist as it belongs to Product which itself belongs to User ?

checklist.save will return false if the checklist failed to save for some reason; presumably because a validation failed .

For example, perhaps your app/models/checklists.rb contains something like:

validates :product_id, presence: true

Or:

validates :content, length: { minimum: 10 }

Etc. In this simple scenario, you can probably easily determine the error by just looking at the model definition; but for a more complex application you could view: checklist.errors.messages to see a list of reasons why the record failed to save.

Judging by the test name ( "should have content" ), my guess is that it's failing because content cannot be blank!

To make this test pass, for example, perhaps you need to write:

test 'should have content' do
  checklist = Checklist.new(content: 'hello world')
  assert checklist.save
end

One common approach that people use when testing this sort of thing is to define a "valid record" in factories ; this lets you explicitly test for invalid records, rather than having to explicitly re-define valid records in lots of place. For example, here you could do:

# test/factories/checklists.rb
FactoryBot.define do
  factory :checklist do
    content 'test content'
  end
end

# test/models/checklist_test.rb
test 'should have content' do
  checklist = build(:checklist, content: nil)
  refute checklist.save # Expecting this to FAIL!
  assert_includes "Content cannot be nil", checklist.errors
end

(Code may not be 100% complete/accurate; but you get the idea)

I have learned Fixtures to solve this problem.

Fixtures are designed in a way that even associated data(association in model) can be done. For example in my test i have written

checklist = checklists(:one)

to get a test data for checklist. In checklists fixtures(checklists.yml)

  one:
    product: one
    content: Entry
    hashtag: '#markets'
    archived: false
    done: false

where

product: one

refers to :one data in products.yml which is

  one:
   user: one
   name: Test
   role: Will decide

and thus association in fixtures is done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM