- Read Tutorial
In this guide we will walk through the process of creating RSpec tests for and then implementing the ability to create records in the database for our Notification resource. There are a few ways that we could test this, however for microservice based applications I typically like to use request specs since this will most closely mimic other applications calling our app. Any helpful tool of Request specs is how they can work with JSON data.
Let's start by creating a spec directory that will hold our request tests:
mkdir spec/requests
Next create a new spec file for our notifications:
touch spec/requests/notification_spec.rb
And we can implement our first test that will see if we can create a new Notification via a RESTful request:
# spec/requests/notification_spec.rb require "rails_helper" RSpec.describe Notification, type: :request do it "creates a Notification" do headers = { "ACCEPT" => "application/json" } post "/notifications", { notification: { phone: "5555555555", body: "My Message", source_app: "my_app_name" } }, headers expect(response.content_type).to eq("application/json") expect(response).to have_http_status(:created) end end
If you're not familiar with RESTful requests this test is sending a POST request to the /notifications route and sending in a hash of values as parameters and it has two expectations:
- The
content_typeto equalapplication/json, which is the format our API will return - The response to include the
httpstatus ofcreated, which we're passing in as a symbol
If we run rspec spec/requests we'll get an expected error saying The action 'create' could not be found for NotificationsController. So let's add that to the NotificationController:
# app/controllers/notifications_controller.rb class NotificationsController < ApplicationController def create end end
Running the request spec will now say that we have a missing template, which isn't the most helpful error message to drive our development since we don't want a template for our create action, but since we're good Rails developers we know that the convention is for the create action to pass the request to the show action, so we'll ignore this for a second and instead implement the ability to create a new Notification via the request:
# app/controllers/notifications_controller.rb class NotificationsController < ApplicationController def create Notification.create(params.permit(:phone, :body, :source_app)) end end
I skipped the step where we didn't implement strong parameters because I'm not a fan of spending time on steps that we already know about, eventually we'll refactor this to use a notification_params method. If you run the specs now you'll see that it's still giving the error message asking for a template, so let's give RSpec what it wants, but instead of rendering an HTML view template we'll create a JSON template:
touch app/views/notifications/show.json.erb
We'll also add in the minimal code necessary for the show action to work in the controller, both in having the create action redirect and creating the show action itself.
# app/controllers/notifications_controller.rb class NotificationsController < ApplicationController def create @notification = Notification.create(params.permit(:phone, :body, :source_app)) respond_to do |format| format.json { render action: 'show', status: :created, location: @notification} end end def show end end
Now all of the tests are passing, I did a little more work in this step then I usually do, so let's go through it step by step:
- I'm storing the newly created
Notificationin an instance variable. - Then I setup a
respond_toblock to tell the application how to respond to respond to requests and setting the: render action, the status, and the location to redirect the user
Now let's refactor this code because it has a few ugly Rails antipatterns. What needs to be fixed? Let's put down a list:
- We're hard coding the strong parameters into the
createmethod call, we'll need to refactor this if we're going to use strong params in any other methods. - We're skipping straight to the
createaction, we should be first instantiating a new instance of theNotificationclass and then using thesavemethod in case there is an issue saving the record to the database.
In the next lesson we're going to go through and refactor this code and correct both of these items.