为什么我的单元测试不反映 PRY 显示我存在的对我的记录的更改?
Why doesn't my unit test reflect the changes to my records that PRY shows me exists?
我的规格中有一个 before :each
,看起来像这样:
before :each do
@user1 = create(:user, gender: 0)
@user2 = create(:user)
@membership1 = create(:membership, member: nil, family_tree: @user1.family_tree, inviter: @user1, invited: @user2, relation: "sister", relative_type: 1)
@membership2 = create(:membership, member: nil, family_tree: @user2.family_tree, inviter: @user2, invited: @user1, relation: "brother", relative_type: 1)
@connection = create(:connection, inviter_membership: @membership1, invited_membership: @membership2, inviter_user: @user1, invited_user: @user2, request_status: 1)
sign_in @user1
end
这是我的单元测试:
it "should swap ownership of the inviter_membership - aka make invited_user the inviter_user on that inviter_membership" do
delete :destroy, id: @user1
expect(@membership1.inviter).to be @user2
end
我的控制器所做的就是销毁通过 ID 传入的记录,如下所示:
def destroy
@user = User.find(params[:id])
if @user.destroy
redirect_to root_path, notice: "You have successfully cancelled your account."
else
redirect_to :back
end
end
但是,在我的 User
模型中,我有一个 before_destroy :callback
并且我的关联是这样的:
class User < ActiveRecord::Base
before_destroy :convert_user_to_members
has_many :memberships
has_many :inviter_memberships, class_name: "Membership", foreign_key: "user_id"
has_many :invited_memberships, class_name: "Membership", foreign_key: "invited_id"
has_many :inviter_connections, class_name: "Connection", foreign_key: "inviter_user_id"
has_many :invited_connections, class_name: "Connection", foreign_key: "invited_user_id"
private
def convert_user_to_members
inviter_mems = self.inviter_memberships
if !inviter_mems.empty?
inviter_mems.each do |membership|
if membership.user?
member = Member.create(first_name: self.first_name, last_name: self.last_name, email: self.email, bio: self.bio, gender: self.gender, avatar: self.avatar, birthday: self.birthday, deceased: false)
invited_user = membership.invited
membership.update!(member: member, inviter: invited_user, invited: nil, relative_type: 0)
if !membership.inviter_connection.nil?
connection = membership.inviter_connection
connection.update!(inviter_membership: membership, invited_membership: nil, inviter_user: invited_user, invited_user: nil, request_status: 3)
end
end
end
end
end
对于位于我测试顶部的第一个binding.pry
(即在调用销毁和执行回调之前),这是我得到的控制台:
78: it "should swap ownership of the inviter_membership - aka make invited_user the inviter_user on that inviter_membership" do
=> 79: binding.pry
80: delete :destroy, id: @user1
81: binding.pry
82: expect(@membership1.inviter).to be @user2
83: end
84: #
[1] pry()> @user1.name
=> "Maybell McKenzie"
[2] pry()> @user2.name
=> "Joey Stanton"
[3] pry()> @membership1.inviter.name
=> "Maybell McKenzie"
[4] pry()> @membership1.invited.name
=> "Joey Stanton"
[5] pry()> @membership1.member
=> nil
对于在我的回调中执行的 第二个 binding.pry
,情况如下:
226: invited_user = membership.invited
227: membership.update!(member: member, inviter: invited_user, invited: nil, relative_type: 0)
=> 228: binding.pry
229: if !membership.inviter_connection.nil?
231: connection = membership.inviter_connection
232: connection.update!(inviter_membership: membership, invited_membership: nil, inviter_user: invited_user, invited_user: nil, request_status: 3)
233: end
[6] pry(#<User>)> self.name
=> "Maybell McKenzie"
[7] pry(#<User>)> invited_user.name
=> "Joey Stanton"
[8] pry(#<User>)> membership.inviter.name
=> "Joey Stanton"
[9] pry(#<User>)> membership.invited
=> nil
[10] pry(#<User>)> membership.member.name
=> "Maybell McKenzie"
注意几点:
- 当前正在评估的记录是
user
记录,它与第一个 binding.pry
中的 @user1
同名 - 这很好。
invited_user
已正确设置为与上述 @user2
相同的用户记录。
membership.inviter.name
现在与 invited_user.name
相同...也就是说...交换已成功。
membership.invited
属性现在设置为 nil
。
- 现在有一个
membership.member
属性,并且已正确设置为与 @user1
相同的用户。
到目前为止,我们还不错。下一次绑定发生在销毁完成之后。这就是事情出错的地方。请记住,在我的 User
模型中,任何 membership
关联都没有 dependent: :destroy
。
但这是第三次的结果binding.pry
:
78: it "should swap ownership of the inviter_membership - aka make invited_user the inviter_user on that inviter_membership" do
79: binding.pry
80: delete :destroy, id: @user1
=> 81: binding.pry
82: expect(@membership1.inviter).to be @user2
83: end
[2] pry()> @user1.name
=> "Maybell McKenzie"
[3] pry()> @user2.name
=> "Joey Stanton"
[4] pry()> @membership1.inviter.name
=> "Maybell McKenzie"
[5] pry()> @membership1.invited.name
=> "Joey Stanton"
[6] pry()> @membership1.member
=> nil
请注意,所有内容看起来都与第一个 binding.pry
相同。
如果你深入挖掘,你会注意到似乎与 @membership1
相关的记录实际上被销毁了....尽管它不应该被销毁。
[7] pry()> Membership.count
=> 1 # this should be 2, because no membership record should be deleted.
[8] pry()> Membership.all
=> [#<Membership id: 1986, family_tree_id: 34158, user_id: 14266, created_at: "2016-01-31 05:29:37", updated_at: "2016-01-31 05:29:37", relation: "brother", member_id: nil, invited_id: 14265, relative_type: 1>]
[9] pry()> @user1.id
=> 14265
[10] pry()> @user2.id
=> 14266
那么,为什么我的测试结果与回调返回的结果不同步?或者如何查看从我的回调发送到测试的确切结果?反正我可以检查一下吗?
我获取一些要更新的记录的方法是在测试中对该实例变量调用 .reload
。
例如:
it "should create a member record with inviter_user's info" do
delete :destroy, id: @user1
@membership2.reload
expect(@membership2.member.name).to eq @user1.name
end
对于先前在测试失败时删除或重新创建的记录,仍然会给出 id
的 nil,但是通过执行 .reload
,实例变量会更新。
我的规格中有一个 before :each
,看起来像这样:
before :each do
@user1 = create(:user, gender: 0)
@user2 = create(:user)
@membership1 = create(:membership, member: nil, family_tree: @user1.family_tree, inviter: @user1, invited: @user2, relation: "sister", relative_type: 1)
@membership2 = create(:membership, member: nil, family_tree: @user2.family_tree, inviter: @user2, invited: @user1, relation: "brother", relative_type: 1)
@connection = create(:connection, inviter_membership: @membership1, invited_membership: @membership2, inviter_user: @user1, invited_user: @user2, request_status: 1)
sign_in @user1
end
这是我的单元测试:
it "should swap ownership of the inviter_membership - aka make invited_user the inviter_user on that inviter_membership" do
delete :destroy, id: @user1
expect(@membership1.inviter).to be @user2
end
我的控制器所做的就是销毁通过 ID 传入的记录,如下所示:
def destroy
@user = User.find(params[:id])
if @user.destroy
redirect_to root_path, notice: "You have successfully cancelled your account."
else
redirect_to :back
end
end
但是,在我的 User
模型中,我有一个 before_destroy :callback
并且我的关联是这样的:
class User < ActiveRecord::Base
before_destroy :convert_user_to_members
has_many :memberships
has_many :inviter_memberships, class_name: "Membership", foreign_key: "user_id"
has_many :invited_memberships, class_name: "Membership", foreign_key: "invited_id"
has_many :inviter_connections, class_name: "Connection", foreign_key: "inviter_user_id"
has_many :invited_connections, class_name: "Connection", foreign_key: "invited_user_id"
private
def convert_user_to_members
inviter_mems = self.inviter_memberships
if !inviter_mems.empty?
inviter_mems.each do |membership|
if membership.user?
member = Member.create(first_name: self.first_name, last_name: self.last_name, email: self.email, bio: self.bio, gender: self.gender, avatar: self.avatar, birthday: self.birthday, deceased: false)
invited_user = membership.invited
membership.update!(member: member, inviter: invited_user, invited: nil, relative_type: 0)
if !membership.inviter_connection.nil?
connection = membership.inviter_connection
connection.update!(inviter_membership: membership, invited_membership: nil, inviter_user: invited_user, invited_user: nil, request_status: 3)
end
end
end
end
end
对于位于我测试顶部的第一个binding.pry
(即在调用销毁和执行回调之前),这是我得到的控制台:
78: it "should swap ownership of the inviter_membership - aka make invited_user the inviter_user on that inviter_membership" do
=> 79: binding.pry
80: delete :destroy, id: @user1
81: binding.pry
82: expect(@membership1.inviter).to be @user2
83: end
84: #
[1] pry()> @user1.name
=> "Maybell McKenzie"
[2] pry()> @user2.name
=> "Joey Stanton"
[3] pry()> @membership1.inviter.name
=> "Maybell McKenzie"
[4] pry()> @membership1.invited.name
=> "Joey Stanton"
[5] pry()> @membership1.member
=> nil
对于在我的回调中执行的 第二个 binding.pry
,情况如下:
226: invited_user = membership.invited
227: membership.update!(member: member, inviter: invited_user, invited: nil, relative_type: 0)
=> 228: binding.pry
229: if !membership.inviter_connection.nil?
231: connection = membership.inviter_connection
232: connection.update!(inviter_membership: membership, invited_membership: nil, inviter_user: invited_user, invited_user: nil, request_status: 3)
233: end
[6] pry(#<User>)> self.name
=> "Maybell McKenzie"
[7] pry(#<User>)> invited_user.name
=> "Joey Stanton"
[8] pry(#<User>)> membership.inviter.name
=> "Joey Stanton"
[9] pry(#<User>)> membership.invited
=> nil
[10] pry(#<User>)> membership.member.name
=> "Maybell McKenzie"
注意几点:
- 当前正在评估的记录是
user
记录,它与第一个binding.pry
中的@user1
同名 - 这很好。 invited_user
已正确设置为与上述@user2
相同的用户记录。membership.inviter.name
现在与invited_user.name
相同...也就是说...交换已成功。membership.invited
属性现在设置为nil
。- 现在有一个
membership.member
属性,并且已正确设置为与@user1
相同的用户。
到目前为止,我们还不错。下一次绑定发生在销毁完成之后。这就是事情出错的地方。请记住,在我的 User
模型中,任何 membership
关联都没有 dependent: :destroy
。
但这是第三次的结果binding.pry
:
78: it "should swap ownership of the inviter_membership - aka make invited_user the inviter_user on that inviter_membership" do
79: binding.pry
80: delete :destroy, id: @user1
=> 81: binding.pry
82: expect(@membership1.inviter).to be @user2
83: end
[2] pry()> @user1.name
=> "Maybell McKenzie"
[3] pry()> @user2.name
=> "Joey Stanton"
[4] pry()> @membership1.inviter.name
=> "Maybell McKenzie"
[5] pry()> @membership1.invited.name
=> "Joey Stanton"
[6] pry()> @membership1.member
=> nil
请注意,所有内容看起来都与第一个 binding.pry
相同。
如果你深入挖掘,你会注意到似乎与 @membership1
相关的记录实际上被销毁了....尽管它不应该被销毁。
[7] pry()> Membership.count
=> 1 # this should be 2, because no membership record should be deleted.
[8] pry()> Membership.all
=> [#<Membership id: 1986, family_tree_id: 34158, user_id: 14266, created_at: "2016-01-31 05:29:37", updated_at: "2016-01-31 05:29:37", relation: "brother", member_id: nil, invited_id: 14265, relative_type: 1>]
[9] pry()> @user1.id
=> 14265
[10] pry()> @user2.id
=> 14266
那么,为什么我的测试结果与回调返回的结果不同步?或者如何查看从我的回调发送到测试的确切结果?反正我可以检查一下吗?
我获取一些要更新的记录的方法是在测试中对该实例变量调用 .reload
。
例如:
it "should create a member record with inviter_user's info" do
delete :destroy, id: @user1
@membership2.reload
expect(@membership2.member.name).to eq @user1.name
end
对于先前在测试失败时删除或重新创建的记录,仍然会给出 id
的 nil,但是通过执行 .reload
,实例变量会更新。