Как я могу издеваться над возвращаемыми значениями ассоциации объектов devise? - PullRequest
2 голосов
/ 15 июля 2011

У меня есть модель Employee, модель Client и модель Office. Devise контролирует логику аутентификации на сотруднике. У меня есть несколько контроллеров, которые подклассов базового контроллера, который устанавливает все необходимое для всех контроллеров (DRY). При тестировании этих контроллеров мне нужно иметь возможность смоделировать возвращенный офис на сотруднике, вошедшем в систему, чтобы тесты контроллера работали правильно, но у меня возникли проблемы.

Вопрос: как я могу заставить пользователя # office вернуть mock_office для current_employee, когда current_employee является реальным объектом.

Вот весь код, необходимый для описания моей проблемы. приложение / модели / employee.rb

class Employee < ActiveRecord::Base
  devise :database_authenticatable, :token_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :lockable, :timeoutable

  attr_accessible :username, :password_confirmation, :password, :email, :office_id

  belongs_to :office
end

приложение / модели / client.rb

class Client < ActiveRecord::Base
  belongs_to :office
end

приложение / модели / office.rb

class Office < ActiveRecord::Base
  has_many :employees
  has_many :clients
end

конфиг / routes.rb

Project::Application.routes.draw do
  devise_for :employees
  namespace :employees do
    resources :clients
  end
end

приложение / контроллеры / сотрудников / base_controller.rb

class Employees::BaseController < ApplicationController
  before_filter :authenticate_employee! && :set_office

private
  def set_office
    @office = current_employee.office
  end
end

приложение / контроллеры / сотрудников / clients_controller.rb

class Employees::ClientsController < Employees::BaseController
  def create
    flash[:notice] = Message::SOME_MESSAGE
  end
end

Спецификация / поддержка / controller_macros.rb

module ControllerMacros
  def login_employee
    let(:current_employee) { Factory(:employee) }
    let(:mock_office) { mock_model Office }

    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:employee]
      sign_in :current_employee, current_employee
      current_employee.should_receive(:office).and_return(:mock_office)
    end
  end
end

спецификация / spec_helper.rb

require 'rubygems'
require 'spork'

Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'

  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    config.mock_with :rspec
    config.fixture_path = "#{::Rails.root}/spec/fixtures"
    config.use_transactional_fixtures = true
    config.include Devise::TestHelpers, :type => :controller

    config.extend ControllerMacros, :type => :controller
  end
end

Spork.each_run do
end

спецификация / контроллеры / сотрудников / clients_controller_spec.rb

require 'spec_helper'

describe Users::ClientsController do
  login_employee

  it { should inherit_from(Users::Admin::BaseController) }

  describe 'basic test' do
    before do
      post :create, {}
    end

    it {should respond_with_content_type(:html)}
  end
end

результаты запуска спецификаций

(in /Users/developer/Development/Workspace/Project.ror3)
/Users/developer/.rvm/rubies/ruby-1.9.2-p180/bin/ruby -S bundle exec rspec ./spec/controllers/employees/clients_controller_spec.rb
No DRb server is running. Running in local process instead ...
.F

Failures:

  1) Users::ClientsController basic test 
     Failure/Error: post :create, {}
     NoMethodError:
       undefined method `office' for nil:NilClass
     # ./app/controllers/employees/base_controller.rb:6:in `set_office'
     # ./spec/controllers/employees/clients_controller_spec.rb:12:in `block (3 levels) in '

Finished in 1.09 seconds
2 examples, 1 failure

Failed examples:

rspec ./spec/controllers/employees/clients_controller_spec.rb:15 # Users::ClientsController basic test 
rake aborted!
ruby -S bundle exec rspec ./spec/controllers/employees/clients_controller_spec.rb failed

(See full trace by running task with --trace)

ПРИМЕЧАНИЕ: было много кода для похудения, чтобы получить всю информацию выше. Я перечитывал много раз и считаю, что проблема не в настройке, а в самом объекте разработки (с использованием sign_in). Если вам нужно больше, пожалуйста, запрос.

1 Ответ

2 голосов
/ 15 июля 2011
module ControllerMacros
  def login_employee
    let(:current_employee) { mock_model Employee }
    let(:mock_office) { mock_model Office }

    before(:each) do
      request.env['warden'] = mock(Warden, :authenticate => current_employee,
                                       :authenticate! => current_employee)
      current_employee.should_receive(:office).and_return(:mock_office)
    end
  end
end
...