Почему этот тест Test::Unit не может сохранить модель через `post :create`?

У меня две модели: User и Topic. У пользователей может быть много тем, и темы принадлежат одному пользователю.

В моем контроллере тем я пытаюсь проверить действие создания для допустимой темы:

Тест

  # topics_controller.test.rb
  def test_create_valid
    sign_in Factory(:user) # Devise will redirect you to the login page otherwise.
    topic = Factory.build :topic
    post :create, :topic => topic
    assert_redirected_to topic_path(assigns(:topic))
  end

Фабрика (Девушка с завода)

# factories.rb
Factory.define :user do |f|
  f.sequence(:username) { |n| "foo#{n}"}
  f.password "password"
  f.password_confirmation { |u| u.password}
  f.sequence(:email) { |n| "foo#{n}@example.com"}
end

Factory.define :topic do |f|
  f.name "test topic"
  f.association :creator, :factory => :user
end

Вывод теста

ERROR test_create_valid (0.59s) 
      ActionController::RoutingError: No route matches {:action=>"show", :controller=>"topics", :id=>#<Topic id: nil, name: nil, created_at: nil, updated_at: nil, creator_id: 1>}
      /usr/local/lib/ruby/gems/1.9.1/gems/actionpack-3.0.7/lib/action_dispatch/routing/route_set.rb:425:in `raise_routing_error'

В тесте topic.valid? верно, а topic.name имеет заводское значение.

Тем не менее, пост, похоже, не дожил до post :create, :topic => topic. Похоже, он никогда не сохранялся в базе данных, так как у него даже нет идентификатора в тестовом выводе.

Редактировать: даже если я обойду Фабрику для новой темы, это не сработает.

  def test_create_valid
    @user = Factory :user
    sign_in @user
    topic = @user.topics.build(:name => "Valid name.")
    post :create, :topic => topic
    assert_redirected_to topic_path(assigns(:topic))
  end

Выдает ту же ошибку теста.


person danneu    schedule 08.05.2011    source источник


Ответы (2)


Метод post здесь ожидает параметры в качестве второго аргумента, а не объекты. Это связано с тем, что действие create в вашем контроллере будет использовать метод params для получения этих параметров и использования их в процессе создания новой темы, используя такой код:

Topic.new(params[:topic])

Поэтому вашим params[:topic] должны быть атрибуты проекта, который вы хотите создать, а не существующий объект Topic. Однако вы можете использовать Factory.build :topic для получения экземпляра объекта Topic, а затем сделать это, чтобы заставить его работать:

post :create, :topic => topic.attributes
person Ryan Bigg    schedule 08.05.2011

Это так далеко от меня, но мне, видимо, пришлось вручную установить атрибут в параметрах post :create. Кажется довольно нелогичным, учитывая, что :topic => topic — это такая идиома Rails.

  def test_create_valid
    sign_in @user
    topic = Factory.build :topic
    post :create, :topic => {:name => topic.name}
    assert_redirected_to topic_path(assigns(:topic))
  end

Надеюсь, кто-нибудь сможет пролить свет на то, почему post :create, :topic => topic не работает.

person danneu    schedule 08.05.2011