Nick Bb
Nick Bb

Reputation: 601

Reset Password testing with Rspec

i am using rails and want to write a test for password reset in Rspec. i am quite new to testing. this is what i have done so far:

require 'rails_helper'

describe UsersController, type: :controller do

describe 'post #reset_password' do
let(:user) { create(:user) }

context "reset password" do  
  def do_request
    patch :update_password
  end

  before { do_request }
  it { expect(ActionMailer::Base.deliveries.count(1) } 
   end
  end
end

every time i run this it gives ma an syntax error in
"it { expect(ActionMailer::Base.deliveries.count(1) } ". i want to check whether the email successfully sent of not and if the user have key in the email. Thanks!

Upvotes: 0

Views: 1668

Answers (2)

MilesStanfield
MilesStanfield

Reputation: 4639

The problems you're having will most likely be fixed by writing better tests. Here's generally how you would write tests for something like this.

Lets suppose in your routes file you have a post route that looks something like this

# config/routes.rb
post "/user/:id/reset_password", to: "users#reset_password"

And your User controller looks something like this

# app/controllers/users_controller.rb
class UsersController
  ...
  def reset_password
    user = User.find(params[:id])
    user.reset_password!
    SomeMailClass.email_reset_instructions(user)
  end
end

and your User.rb model looks something like this

# app/models/user.rb
class User < ActiveRecord::Base
  def reset_password!
    update!(password: nil) # or whatever way you want/need to reset the password
  end
end

and you have some type of mailing class to send your email

# app/models/some_mail_class.rb
class SomeMailClass
  def self.email_reset_instructions(user)
    # do something to send email...
  end
end

The way you would go about testing this in the controller would be

# spec/controllers/users_controller_spec.rb
require 'rails_helper'

describe UsersController, type: :controller do
  it "#reset_password" do
    user_id = double(:user_id)
    user = double(:user)
    expect(User).to receive(:find).with(user_id).and_return(user)
    expect(user).to receive(:reset_password!).and_return(true)
    expect(SomeMailClass).to receive(:email_reset_instructions).with(user)
    post :reset_password, id: user_id
  end
end

But you shouldn't stop there. Because the implementation of the newly made method reset_password! and the SomeMailClass has yet to be tested. So you would write model/unit tests like this for them

# spec/models/user_spec.rb
require "rails_helper"

describe User do
  it ".reset_password!" do
    user = User.create(password: "foo")
    expect(user.password).to eq "foo"
    user.reset_password!
    expect(user.password).to eq nil
  end
end

Then you might install vcr and factory_girl gems and use them like so to test your mailer

# spec/models/some_mail_class_spec.rb
require "rails_helper"

describe SomeMailClass do
  VCR.use_cassette "email_reset_instructions" do |cassette|
    it ".email_reset_instructions" do
      user = FactoryGirl.create(:user)
      SomeMailClass.email_reset_instructions(user)
      # you can write some expectations on the cassette obj to test. 
      # or you can write whatever expectations you need/desire
    end
  end
end

And in the end if there was something happening on the front end that a user would click that made this post request you would write a feature test for it as well.

Hope this helps!

Upvotes: 0

Rajarshi Das
Rajarshi Das

Reputation: 12330

1) you miss ) at last here so got syntax error

it { expect(ActionMailer::Base.deliveries.count(1) } 

to

it { expect(ActionMailer::Base.deliveries.count(1)) } 

2) If you want to check total deliveries. you can try

  it 'should send an email' do
    ActionMailer::Base.deliveries.count.should == 1
  end

also check sender

it 'renders the sender email' do  
    ActionMailer::Base.deliveries.first.from.should == ['[email protected]']
end

Also check subject line

it 'should set the subject to the correct subject' do
    ActionMailer::Base.deliveries.first.subject.should == 'Here Is Your Story!'
end

Upvotes: 1

Related Questions