Eri*_*icM 6 ruby tdd rspec ruby-on-rails rspec-rails
我在使用instance_double时遇到间歇性测试失败.
我有一个包含4个规格的文件.这是来源:
require 'rails_helper'
describe SubmitPost do
before(:each) do
@post = instance_double('Post')
allow(@post).to receive(:submitted_at=)
end
context 'on success' do
before(:each) do
allow(@post).to receive(:save).and_return(true)
@result = SubmitPost.call(post: @post)
end
it 'should set the submitted_at date' do
expect(@post).to have_received(:submitted_at=)
end
it 'should call save' do
expect(@post).to have_received(:save)
end
it 'should return success' do
expect(@result.success?).to eq(true)
expect(@result.failure?).to eq(false)
end
end
context 'on failure' do
before(:each) do
allow(@post).to receive(:save).and_return(false)
@result = SubmitPost.call(post: @post)
end
it 'should return failure' do
expect(@result.success?).to eq(false)
expect(@result.failure?).to eq(true)
end
end
end
Run Code Online (Sandbox Code Playgroud)
这是一个Rails 4.1.4应用程序.在内部,SubmitPost设置submitted_at并调用保存在传入的Post上.我的帖子模型如下所示:
class Post < ActiveRecord::Base
validates :title, presence: true
validates :summary, presence: true
validates :url, presence: true
validates :submitted_at, presence: true
scope :chronological, -> { order('submitted_at desc') }
end
Run Code Online (Sandbox Code Playgroud)
这是超级香草.
当我跑rake,rspec或者bin/rspec,我得到所有四个测试都失败了20% - 30%的时间.错误消息始终是:
Failure/Error: allow(@post).to receive(:submitted_at=)
Post does not implement: submitted_at=
Run Code Online (Sandbox Code Playgroud)
如果我标注其中一个规格focus: true,那么一个规格将在100%的时间内失败.
如果我更换instance_double用double,所有的规格会成功的100%的时间.
看来instance_double在推断Post类上可用的方法方面有些困难.它似乎也有点随机和基于时间.
有没有人遇到过这个问题?什么想法可能是错的?如何解决这个问题的任何意义?当然,插入调试断点会导致规范100%的时间通过.
您看到的问题是 ActiveRecord 动态创建列方法。instance_double用于'Post'查找方法来验证您是否正确地存根它们(除非该类尚不存在或尚未加载)。
当先前的规范加载模型时,ActiveRecord 将创建这些动态方法,以便您的规范通过,然后 RSpec 可以找到这些方法(通过调用respond_to?)。当单独运行时,该模型以前没有被使用过,因此 ActiveRecord 还不会创建动态方法,并且您的测试会像您所经历的那样失败。
解决方法是强制 ActiveRecord 在规范中调用动态方法时加载它们:
class Post < ActiveRecord::Base
def submitted_at=(value)
super
end
end
Run Code Online (Sandbox Code Playgroud)
请参阅 RSpec 文档以获取该问题的进一步说明和解决方法:
https://www.relishapp.com/rspec/rspec-mocks/docs/verifying-doubles/dynamic-classes
| 归档时间: |
|
| 查看次数: |
1117 次 |
| 最近记录: |