• Skip to primary navigation
  • Skip to main content
  • Skip to footer
Code The Dream School
Code the Dream Labs Logo

Code The Dream School

Main hub for class materials for Code the Dream’s classes

  • Code the Dream Home

Search Code The Dream School

Some Help for FactoryBot and Rspec

Several people have found the rspec homework pretty hard. This page explains some things that may help.

Notes on FactoryBot

When you run tests, there is a temporary database set up just for the time that the test is running. You can use FactoryBot to create test entries. FactoryBot.create creates and saves a new customer in this test database — so the new object will be saved at Customer.last. FactoryBot.attributes_for returns attributes that match your object, but it doesn’t save a new object in the test database. See more on FactoryBot’s methods here: https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#build-strategies”

In the exercise, you are asked to create factories for order and customer objects. Now, for customer, that isn’t too hard. But each order belongs to a customer. So the factory for order has to create the customer object too. This is done as follows:

FactoryBot.define do
  factory :order do
    product_name { "MyString" }
    product_count { 1 }
    association :customer
  end
end

The key point here is the use of association. Now, we can do order = FactoryBot.create(:order) and it will create an order for us and store it in the database. Unfortunately, that doesn’t quite solve all our problems. For the post method, we need to get the attributes for an order object. If we do attributes = FactoryBot.attributes_for(:order) it will not store anything in the database. It will also not create any attributes corresponding to the customer. So we have to create the customer object explicitly, and add its id to the list of attributes, as follows:

customer = FactoryBot.create(:customer)
order_attributes = FactoryBot.attributes_for(:order, customer_id: customer.id)

Now we can call the post method and create the order entry:

    expect { post orders_path, params: {order: order_attributes}
    }.to change(Order, :count)
      expect(response).to redirect_to order_path(id: Order.last.id)

RSpec Detail: The Put Method

If you do bin/rails routes, you will get output that show your current routes, and that shows you what you need to test in your request tests. In, particular, you will have one like this:

 PUT    /orders/:id(.:format)                       orders#update

You need to test whether a put method within rspec will really update the corresponding order entry, using the update method of the orders controller. Well, since we are updating an entry, we better create it first:

order = FactoryBot.create(:order)

Now, we are going to update this with a valid change (you also need to check whether invalid changes are handled correctly. The change we are making will set the product_count to 17. This can be done as follows:

put order_path(id: order.id), params: {order: {product_count: 17}}

Note that you must pass the order.id to the order_path to get to the right order. Note also that the params are a hash within a hash. Now we need to check two things. FIrst, did the product_count actually get changed to 17 in the database? Second, when you do an update, the method is supposed to redirect to the show path for that entry; does it? For the first, we have to do an order.reload so that the copy of the order in memory matches what is in the database. For the second, we have the response object, which, in rspec request testing, is always set to the result of the operation, i.e. what it returns. So:

order.reload
expect(order.product_count).to eq(17)
expect(response).to redirect_to order_path(id: order.id)

I hope this gives enough help that you can complete the exercise.

Footer

Copyright © 2025 Code the Dream School | All Rights Reserved | Privacy Policy