Тестирование контроллеров в Rails 3 с Devise и RSpec - PullRequest
2 голосов
/ 18 ноября 2010

Я пытаюсь проверить действие моего контроллера create.Я использую Devise для аутентификации и использовал метод before_filter, чтобы ограничить доступ к действию create вошедшим в систему пользователям.Вот соответствующая часть моего контроллера.

class RawDataSetsController < ApplicationController
  before_filter :authenticate_user!, :except => [:show, :index, :download]

  def create
    @raw_data_set = current_user.raw_data_sets.build(params[:raw_data_set])
    if @raw_data_set.save
      redirect_to @raw_data_set
    else
      render "new"
    end
  end
end

В моем тестовом примере я хочу убедиться, что вошедший в систему пользователь может создать RawDataSet.Я думаю, что я смоделировал аутентифицированного пользователя в соответствии с инструкциями в этом сообщении в блоге.

require 'spec_helper'
describe RawDataSetsController do

  include Devise::TestHelpers

  def mock_users(stubs={})
    @user ||= mock_model(User, stubs).as_null_object
  end

  def log_in_test_user
    attr = { :username => "Foobar", :email => "doineedit@foobar.com" }
    #mock up an authentication in warden as per http://www.michaelharrison.ws/weblog/?p=349
    request.env['warden'] = mock(Warden, :authenticate => mock_users(attr),
                                         :authenticate! => mock_users(attr),
                                         :authenticate? => mock_users(attr))
  end

  before do
    @rds = Factory(:raw_data_set)
  end

  describe "POST 'create'" do

    before do
      @attr = { 
        :organism_name => "Beef Jerky",
        :mass_spec_type => "My Stomach",
      }
    end

    describe "logged in user" do
      it "should create a raw_data_set when the user is logged in" do
        log_in_test_user
        lambda do
          post :create, :raw_data_set => @attr
        end.should change(RawDataSet, :count).by(1)
      end
    end
  end
end

Запуск этого теста вызывает следующую ошибку:

1) RawDataSetsController POST 'create' logged in user should create a raw_data_set when the user is logged in
 Failure/Error: post :create, :raw_data_set => @attr
 undefined method `user_url' for #<RawDataSetsController:0x0000010175af88>
 # ./app/controllers/raw_data_sets_controller.rb:7:in `create'

Я озадачен этой ошибкой.После дополнительной проверки @raw_data_set является не экземпляром класса модели RawDataSet, а пользователем?Вот как это выглядит, когда я p @raw_data_set

#<User:0x807a06a4 @name="User_1002">

Что, черт возьми, происходит?Что я делаю неправильно?Как я могу проверить действие create на моем контроллере с аутентифицированным пользователем?

Ответы [ 2 ]

1 голос
/ 19 ноября 2010

РЕДАКТИРОВАТЬ (полностью удалена неправильная первая попытка)

Вызов as_null_object, по сути, говорит макету принимать все сообщения, которые не заглушены, и просто возвращать себя. Поэтому, когда вы звоните

current_user.raw_data_sets.build(params[:raw_data_set])

, который обычно возвращает новый RawDataSet, связанный с current_user, вместо этого вы снова получаете current_user.

Поэтому, когда вы пытаетесь вызвать перенаправление, передавая @raw_data_set, вы передаете ему макет вместо RawDataSet экземпляра, таким образом, ошибочный вызов user_url.

Я думаю, что способ справиться с этим - просто использовать реального пользователя (или фабрику) и отключить методы Devise. Таким образом, ваш mock_users становится (например):

  def mock_users(stubs={})
    @user = User.create(stubs)
  end

Теперь current_user фактически выполнит сборку и сохранение с помощью ассоциации.

Пуристы скажут вам издеваться и заглушать все, пока вы не посинете на лице. Винт это - у тебя есть дела поважнее. :)

Другой способ сделать это - проверить, получено ли сообщение о сборке, не проверяя, успешно ли сохранено. Предположительно ваши модельные тесты подтвердят, что сохранение с помощью ассоциации работает - зачем тестировать снова в контроллере?

0 голосов
/ 28 июля 2011

Если вам нужно сделать что-то конкретное, например, изменить поведение входа в систему, вы можете наследовать от разработки контроллеров и перезаписывать их.Вы можете следовать инструкции здесь https://github.com/plataformatec/devise конфигурирующих контроллеров.

...