- 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_type
to equalapplication/json
, which is the format our API will return - The response to include the
http
status 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
Notification
in an instance variable. - Then I setup a
respond_to
block 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
create
method 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
create
action, we should be first instantiating a new instance of theNotification
class and then using thesave
method 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.