为什么我的单元测试不反映 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 模型中,任何 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,实例变量会更新。