admin 管理员组文章数量: 1086019
In this code, sync_external
accepts an array of posts and modifies it by calling a sync method from an external module ExternalService
, which is mocked in the test.
Assume there's some reason to pass a block to sync
. In this trivial example, the block exists to push every yielded response onto a responses array.
Code:
class Post
def self.sync_external(posts)
responses = []
ExternalService.sync(posts) do |response|
responses << response
end
return responses
end
end
RSpec:
let(:responses) {[]}
before do
allow(ExternalService).to receive(sync).with(anything)
.then{responses.inject(_1){|m, response| m.and_yield(response)}}
end
it "sync posts with 100 words successfully" do
posts = FactoryBot.build_list(:post, 10, words: 100)}
posts.each{|post| responses << 200}
expect(Posts.sync_external(posts)).to eq(Array.new(10, 200))
end
Actual result:
allow
evaluates in the before
block when the responses array was empty, so it yielded nothing.
Expected result:
allow
evaluates in the before
block, but re-evaluates and_yield
when the mocked method is called. This will let each it
assign different responses, while keeping the allow
mock in the before
block.
Edit (Solution):
Passing in a block argument and calling the block multiple times is equivalent to chaining .and_yield
multiple times, but useful for evaluating other RSpec variables at runtime.
allow(ExternalService).to receive(sync).with(anything) do |_, &b|
responses.each{b.call(_1)}
end
Thanks to @engineersmnky for his solution here:
本文标签: rubyRSpecreevaluate allow andyield when mocked method is calledStack Overflow
版权声明:本文标题:ruby - RSpec -- re-evaluate allow .and_yield when mocked method is called - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1744063033a2527075.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论