如何避免使用expect_any_instance_of锤子?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何避免使用expect_any_instance_of锤子?相关的知识,希望对你有一定的参考价值。

我有几个像这样的测试:

it 'should invite user again' do
    admin_user = create(:invited_admin_user)
    expect_any_instance_of(AdminUser).to receive(:invite!).and_return(true)
    patch :reinvite, params: { id: admin_user.to_param }
end

我真的想这样写:

it 'should invite user again' do
    admin_user = create(:invited_admin_user)
    expect(admin_user).to receive(:invite!).and_return(true)
    patch :reinvite, params: { id: admin_user.to_param }
end

但如果我这样做,测试就会失败。知道为什么会这样吗?我正在使用factory_bot来创建AdminUser实例。

我已经尝试在测试中使用puts语句,并使用invite方法来确认ID。

def invite!(_param1 = AdminUser.new, _param2 = {})
    puts 'ID in invite!' + self.id.inspect
    super(_param1, _param2)
end

it 'should invite user again' do
    admin_user = create(:invited_admin_user)
    puts 'adminuser created' + admin_user.id.inspect
    expect(admin_user).to receive(:invite!).and_return(true)
    patch :reinvite, params: { id: admin_user.to_param }
end

结果

adminuser created7768

邀请中的ID!7768

答案

你为什么一开始想在这里使用模拟?

it 'should invite user again' do
  admin_user = create(:invited_admin_user)
  patch :reinvite, params: { id: admin_user.to_param }
  expect(admin_user.reload.invited).to eq(true)
end

如果你想避免对数据库的冗余调用,整个测试应该写成a)没有真正的DB对象创建(FactoryGirl#build,)b)没有patch调用(直接调用相应的控制器的方法)和c)模拟一切都是在两者之间呼唤。

NB我个人认为没有任何理由可以测试所有内容都被嘲笑:它们与代码本身几乎没有区别。我的意思是,我们可能在测试和代码中犯了一个错误,并检查patch调用相应控制器的方法是愚蠢的:它已经在Rails测试中检查过了。我总是尝试测试真实的东西,如果适用的话(比如用户确实被改变了,而不是调用了一些方法。)

另一答案

问题是您的代码重新查找记录并将其实例化为新对象,因此接收消息的对象与测试中的对象不同。

为了解决这个问题:

it 'should invite user again' do
  admin_user = create(:invited_admin_user)
  expect(User).to receive(:find).with(admin_user.id).and_return(admin_user)
  expect(admin_user).to receive(:invite!).and_return(true)
  patch :reinvite, params: { id: admin_user.to_param }
end

这只是拦截User.find调用并返回您的测试对象而不是通常初始化的对象。

以上是关于如何避免使用expect_any_instance_of锤子?的主要内容,如果未能解决你的问题,请参考以下文章

AsyncController 如何避免使用 ASP.NET 工作线程?

使用 findContours 时如何避免检测到图像帧

VBA如何在使用许多整数时避免递归

如何避免“从未使用方法”消息?

使用pow时如何避免浮点异常? [关闭]

[在使用 PyVirtualDisplay 时] 如何避免挂起 Xvfb 进程?