单元测试与固定装置的多态关联
Unit testing a polymorphic association with fixtures
我收到此错误消息:
ERROR["test_profile_display", UsersProfileTest, 2.569931] test_profile_display#UsersProfileTest (2.57s)
NoMethodError: NoMethodError: undefined method `posts' for nil:NilClass
app/controllers/users_controller.rb:14:in `show'
test/integration/users_profile_test.rb:22:in `block in <class:UsersProfileTest>'
app/controllers/users_controller.rb:14:in `show'
test/integration/users_profile_test.rb:22:in `block in <class:UsersProfileTest>'
@posts = @user.character.posts.paginate(page: params[:page])
行中的 UsersController 中的 character
似乎为零。用户和角色之间存在多态关系。我以为我在 fixtures 中使用了正确的语法来告诉 rails 用户 Bazley 有一个 fixture:
在 characters.yml:
character_bazley:
sociable: bazley (user)
如何让 rails 相信用户 fixture 确实有一个属于它的角色?
test/integration/users_profile_test.rb:
require 'test_helper'
class UsersProfileTest < ActionDispatch::IntegrationTest
include ApplicationHelper
def setup
@user = users(:bazley)
end
test "profile display" do
log_in_as(@user)
get user_path(@user)
assert_template 'users/show'
assert_select 'title', full_title(@user.name)
assert_select 'h1', text: @user.name
assert_select 'h1>img.gravatar'
assert_match @user.character.posts.count.to_s, response.body
assert_select 'div.pagination'
@user.character.posts.paginate(page: 1).each do |post|
assert_match post.content, response.body
end
end
end # UsersProfileTest
user.rb:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token, :reset_token
has_one :character, as: :sociable, dependent: :destroy
.
.
end
character.rb:
class Character < ActiveRecord::Base
belongs_to :sociable, polymorphic: true
has_many :posts, dependent: :destroy
validates :sociable_id, presence: true
end # Character
users.yml:
bazley:
name: Bazley
email: bazley@oxdorf.com
callsign: bazley
password_digest: <%= User.digest('password') %>
admin: true
activated: true
activated_at: <%= Time.zone.now %>
characters.yml:
character_bazley:
sociable: bazley (user)
在用户控制器中:
def show
@user = User.find_by_callsign(params[:callsign])
@posts = @user.character.posts.paginate(page: params[:page]) # the line causing the error
@page_name = "user_page"
redirect_to root_url and return unless @user.activated
end
将characters.yml
改为
character_bazley:
sociable: bazley (User)
而不是
character_bazley:
sociable: bazley (user)
注意它是 User
而不是 user
。这里使用的关键字 User
表示 sociable_type
属于 User
class.
参考:
http://ruby-journal.com/rails/define-fixtures-with-polymorphic-association/
http://api.rubyonrails.org/v3.2.8/classes/ActiveRecord/Fixtures.html#label-Polymorphic+belongs_to
我收到此错误消息:
ERROR["test_profile_display", UsersProfileTest, 2.569931] test_profile_display#UsersProfileTest (2.57s)
NoMethodError: NoMethodError: undefined method `posts' for nil:NilClass
app/controllers/users_controller.rb:14:in `show'
test/integration/users_profile_test.rb:22:in `block in <class:UsersProfileTest>'
app/controllers/users_controller.rb:14:in `show'
test/integration/users_profile_test.rb:22:in `block in <class:UsersProfileTest>'
@posts = @user.character.posts.paginate(page: params[:page])
行中的 UsersController 中的 character
似乎为零。用户和角色之间存在多态关系。我以为我在 fixtures 中使用了正确的语法来告诉 rails 用户 Bazley 有一个 fixture:
在 characters.yml:
character_bazley:
sociable: bazley (user)
如何让 rails 相信用户 fixture 确实有一个属于它的角色?
test/integration/users_profile_test.rb:
require 'test_helper'
class UsersProfileTest < ActionDispatch::IntegrationTest
include ApplicationHelper
def setup
@user = users(:bazley)
end
test "profile display" do
log_in_as(@user)
get user_path(@user)
assert_template 'users/show'
assert_select 'title', full_title(@user.name)
assert_select 'h1', text: @user.name
assert_select 'h1>img.gravatar'
assert_match @user.character.posts.count.to_s, response.body
assert_select 'div.pagination'
@user.character.posts.paginate(page: 1).each do |post|
assert_match post.content, response.body
end
end
end # UsersProfileTest
user.rb:
class User < ActiveRecord::Base
attr_accessor :remember_token, :activation_token, :reset_token
has_one :character, as: :sociable, dependent: :destroy
.
.
end
character.rb:
class Character < ActiveRecord::Base
belongs_to :sociable, polymorphic: true
has_many :posts, dependent: :destroy
validates :sociable_id, presence: true
end # Character
users.yml:
bazley:
name: Bazley
email: bazley@oxdorf.com
callsign: bazley
password_digest: <%= User.digest('password') %>
admin: true
activated: true
activated_at: <%= Time.zone.now %>
characters.yml:
character_bazley:
sociable: bazley (user)
在用户控制器中:
def show
@user = User.find_by_callsign(params[:callsign])
@posts = @user.character.posts.paginate(page: params[:page]) # the line causing the error
@page_name = "user_page"
redirect_to root_url and return unless @user.activated
end
将characters.yml
改为
character_bazley:
sociable: bazley (User)
而不是
character_bazley:
sociable: bazley (user)
注意它是 User
而不是 user
。这里使用的关键字 User
表示 sociable_type
属于 User
class.
参考:
http://ruby-journal.com/rails/define-fixtures-with-polymorphic-association/ http://api.rubyonrails.org/v3.2.8/classes/ActiveRecord/Fixtures.html#label-Polymorphic+belongs_to