T
T
therhino2015-02-26 18:07:27
Ruby on Rails
therhino, 2015-02-26 18:07:27

How to test a module?

There is an authenticable.rb module :

module Authenticable
  
  def current_user
    @current_user ||= User.find_by(auth_token: request.headers['Authorization'])
  end

  def authenticate_with_token!
    render json: { errors: "Not authenticated" },
                status: :unauthorized unless user_signed_in?
  end

  def user_signed_in?
    current_user.present?
  end

end

In my code, I use it to prevent unauthorized access, something like this:
# app/controllers/api/v1/appication_controller.rb
class Api::V1::ApplicationController < ActionController::Base
  protect_from_forgery with: :null_session

  include Authenticable
end

# app/controllers/api/v1/users_controller.rb
class Api::V1::UsersController < Api::V1::ApplicationController
  respond_to :json
  before_filter :authenticate_with_token!, only: [:update, :destroy]
....
.....
end

There is a test authenticable_spec.rb :
require 'rails_helper'

class Authentication < ActionController::Base
  include Authenticable
end

describe Authenticable do
  let(:authentication) { Authentication.new }
  subject { authentication }

  describe "#authenticate_with_token" do
    before do
      authentication.stub(:current_user).and_return(nil)
      ??????
    end

    it "render a json error message" do
      expect(json_response[:errors]).to eql "Not authenticated"
    end

  	it { response.status.should eq 401 }
  end

What do I need to write instead of ?????? to make the tests work?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
J
Jeiwan, 2015-02-26
@therhino

describe '.authenticate_with_token' do
  before do
    allow(authentication).to receive(:current_user).and_return(nil)
    allow(authentication).to receive(:render) do |args| # возвращаем аргументы
      args
    end
  end

  it 'returns error' do
    expect(authentication.authenticate_with_token![:json][:errors]).to eq 'Not authenticated'
  end

  it 'returns unauthorized status' do
    expect(authentication.authenticate_with_token![:status]).to eq :unauthorized
  end
end

Your mistake is that you think you are testing a controller. In fact, the controller is needed here only to be able to test the methods of the module (you can even take a bare class to include the module). And the method responsewill not be available here, since we are testing the module, not the controller.

T
therhino, 2015-02-26
@therhino

When to use a naked class

class Authentication
  include Authenticable
end

then an error is thrown
Authenticable.authenticate_with_token returns error
     Failure/Error: allow(authentication).to receive(:render) do |args|
       #<Authentication:0xb982078> does not implement: render

So allow allows you to mock only existing methods?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question