【问题标题】:Rspec Mocking: ActiveRecord::AssociationTypeMismatchRspec 模拟:ActiveRecord::AssociationTypeMismatch
【发布时间】:2011-06-20 10:39:47
【问题描述】:

我是 Rspec 的新手,正在尝试为用户配置文件设置测试。个人资料属于用户。

现在,我通过用户模型与第三方网站进行了 API 集成,但该 API 链接的一些信息包含在 Profile 中,因此我在 Profile 上有一个“after_update”过滤器来告诉父级用户保存,这会触发 API 的更新。

我正在尝试为此编写一个测试,但我得到了一个 ActiveRecord::AssociationTypeMismatch。原因是我使用的是模拟用户,但我正在尝试测试更新配置文件时它会发送 :save 给用户。另外,User 模型有一个电子邮件确认过程,并且在它的创建过程中调用了上述 API,因此实际上创建一个用户只是为了测试这一点并不理想。

这是我的测试:

it "should save the parent user object after it is saved" do
    user = double('user', :save => true )
    profile = Profile.create( :first_name => 'John', :last_name => 'Doe' )
    profile.user = user

    user.should_receive(:save)
end

因此,显然 ActiveRecord 错误是由于尝试将模拟用户与期望真实用户关联的个人资料相关联而引起的。

我的问题是,如何在编写 Rails 测试时避免这种问题?我想要这个测试做的就是确保 Profile 调用 :save 在它的父用户上。有没有更聪明的方法来做到这一点,或者 ActiveRecord 错误的解决方法?

谢谢!

【问题讨论】:

  • 就我个人而言,我会使用 factory_girl 之类的东西来制作一个已经确认的 User 对象,然后对其设置 save 期望值。您是否无法在不通过电子邮件流程的情况下伪造已确认的用户?这引发了一些关于代码设计的警报。
  • 好吧,你的建议最终成为我不得不走的路。通过告诉控制器不要在测试环境中触发该调用,我能够隔离我不想调用的 API,这样我就可以按预期使用工厂对象。但是,我不得不重新打开 API 操作来测试集成,所以最后我放弃了这种方法,并允许 API 的沙箱环境充满了我必须定期清除的垃圾数据。不是我想要的,但它让我可以测试。

标签: ruby-on-rails ruby-on-rails-3 activerecord mocking rspec


【解决方案1】:

您应该可以为此使用mock_model

it "should save the parent user object after it is saved" do
  user = mock_model(User)
  user.should_receive(:save).and_return(true)
  profile = Profile.create( :first_name => 'John', :last_name => 'Doe' )
  profile.user = user
end

【讨论】:

【解决方案2】:

我发现解决这个问题的唯一方法是使用工厂用户而不是模拟用户。这很令人沮丧,但是在测试两个 ActiveRecord 模型之间的回调时,您必须使用真实模型,否则保存调用将失败,生命周期将不会发生,并且无法测试回调。

【讨论】:

  • 不应该在相关模型规范中测试回调吗?
  • 你救了我的命
猜你喜欢
  • 2017-07-08
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 2021-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
相关资源
最近更新 更多