测试回调在父级被销毁时被调用或不被调用(dependent: :destroy)
Testing a callback is called or not called when parent is destroyed (dependent: :destroy)
我想知道是否有一种方法可以测试当父对象通过 dependent: :destroy
触发销毁时是否调用子对象的回调 (before/after_destroy
)?显然我们不能访问destroy过程中创建的对象。
如果有帮助,我正在使用 MiniTest 和 Mocha gem。我怀疑这可能与模拟关系和方法有关?
您应该测试 before/after_destroy 块中的转换是否完成。
它更新数据库了吗?被模拟的对象被调用了吗?
取决于我们希望使用多严格的隔离。
假设我们在 Rails 4:
中有这个例子
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
after_destroy :after_destroy_method
def after_destroy_method
end
end
class Comment < ActiveRecord::Base
belongs_to :post
end
无论如何我都建议使用一些隔离,因为 Post 的模型没有责任知道评论被销毁后会发生什么。因此,测试回调的正确行为应该进入 Comment 模型测试。
严格隔离:
我们知道如果我们将 dependent: :destroy
应用到关系上,那么 Rails 将完成它的工作并调用回调(它已经过测试并且工作得很好)。所以唯一要测试的是:
- 我们在正确的地方使用了
dependent: :destroy
。为此,我们可以在 Post 模型测试中使用 Shoulda Matchers,如下所示:should have_many(:comments).dependent(:destroy)
不那么严格隔离:
离集成测试越来越近了,在Post模型测试中:
test "calls #after_destroy_method on the comments after a post gets destroyed" do
post = Post.create title: "Test title"
Comment.create post: post
Comment.any_instance.expects(:after_destroy_method)
post.destroy
end
我想知道是否有一种方法可以测试当父对象通过 dependent: :destroy
触发销毁时是否调用子对象的回调 (before/after_destroy
)?显然我们不能访问destroy过程中创建的对象。
如果有帮助,我正在使用 MiniTest 和 Mocha gem。我怀疑这可能与模拟关系和方法有关?
您应该测试 before/after_destroy 块中的转换是否完成。
它更新数据库了吗?被模拟的对象被调用了吗?
取决于我们希望使用多严格的隔离。
假设我们在 Rails 4:
中有这个例子class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
after_destroy :after_destroy_method
def after_destroy_method
end
end
class Comment < ActiveRecord::Base
belongs_to :post
end
无论如何我都建议使用一些隔离,因为 Post 的模型没有责任知道评论被销毁后会发生什么。因此,测试回调的正确行为应该进入 Comment 模型测试。
严格隔离:
我们知道如果我们将 dependent: :destroy
应用到关系上,那么 Rails 将完成它的工作并调用回调(它已经过测试并且工作得很好)。所以唯一要测试的是:
- 我们在正确的地方使用了
dependent: :destroy
。为此,我们可以在 Post 模型测试中使用 Shoulda Matchers,如下所示:should have_many(:comments).dependent(:destroy)
不那么严格隔离:
离集成测试越来越近了,在Post模型测试中:
test "calls #after_destroy_method on the comments after a post gets destroyed" do
post = Post.create title: "Test title"
Comment.create post: post
Comment.any_instance.expects(:after_destroy_method)
post.destroy
end