为什么这个 Test::Unit 测试不能在 `post:create` 中保留模型?

发布于 2024-11-05 20:57:01 字数 1708 浏览 6 评论 0原文

我有两个模型:UserTopic。用户可以拥有多个主题,并且主题属于一个用户。

在我的主题控制器中,我尝试测试有效主题的创建操作:

测试

  # 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? 为 true,并且 topic.name 具有来自工厂的值。

然而,这篇文章似乎没有通过 post :create, :topic =>主题。看起来它从未保存在数据库中,因为它在测试输出中甚至没有 id。

编辑:即使我绕过新主题的工厂,它也不起作用。

  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

结果相同的测试错误。

I have two models: User and Topic. Users can have many topics and topics belong to one user.

In my Topics controller, I'm trying to test the create action for a valid topic:

The Test

  # 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

The Factory (Factory Girl)

# 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

The Test Output

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'

In the test, topic.valid? is true and topic.name has a value from the factory.

However, the post doesn't seem to make it past post :create, :topic => topic. It looks like it's never saved in the database since it doesn't even have an id in the test output.

Edit: Even if I bypass the Factory for the new topic, it doesn't work.

  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

Results in the same test error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蹲墙角沉默 2024-11-12 20:57:01

这里的 post 方法需要参数作为第二个参数,而不是对象。这是因为控制器中的 create 操作将使用 params 方法来检索这些参数,并在创建新主题的过程中使用它们,使用如下代码 因此,

Topic.new(params[:topic])

您的 params[:topic] 需要是您要创建的项目的属性,而不是现有的 Topic 对象。但是,您可以使用 Factory.build :topic 来获取实例化的 Topic 对象,然后执行以下操作以使其正常工作:

post :create, :topic => topic.attributes

The post method here expects parameters as the second argument, not objects. This is because the create action in your controller is going to be using the params method to retrieve these parameters and use them in the process of creating a new topic, using code like this:

Topic.new(params[:topic])

So therefore your params[:topic] needs to be the attributes of the project you want to create, not an existing Topic object. However, you could use Factory.build :topic to get an instantiated Topic object and then do this to make it work:

post :create, :topic => topic.attributes
谜泪 2024-11-12 20:57:01

这远远超出了我的能力范围,但我显然必须在 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 不起作用。

This is so far beyond me, but I apparently had to manually set the attribute in the post :create params. Seems pretty counter-intuitive given that :topic => topic is such a Rails idiom.

  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

Hopefully someone can shed some light on why post :create, :topic => topic wouldn't work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文