类已泄漏到另一个示例中,并且不能再在规范中使用
我无法在本地复制此此内容,但是由于某种原因,我在CircleCi运行测试时会遇到以下错误:
<Double Mylogger> was originally created in one example but has leaked into another example and can no longer be used. rspec-mocks' doubles are designed to only last for one example, and you need to create a new one in each example you wish to use it for.
这是我的代码的简化版本:
# frozen_string_literal: true
describe 'my_rake_task' do
let(:my_log) { Mylogger.new }
subject { Rake::Task['my_rake_task'].execute }
describe 'one' do
context 'logs' do
let(:logs) do
[
['My message one'],
['My message two'],
]
end
after { subject }
it 'correctly' do
logs.each { |log| expect(my_log).to receive(:info).with(*log) }
end
end
end
describe 'two' do
context 'logs' do
let(:logs) do
[
['My message three'],
['My message four'],
]
end
after { subject }
it 'correctly' do
logs.each { |log| expect(my_log).to receive(:info).with(*log) }
end
end
end
end
为什么说mylogger是双重的?为什么会泄漏?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
错误指出
MyLogger
是双精度型的原因是因为它是一型。当您调用expect(my_log).to receive
或allow(my_log).to receive
时,您将实例转换为 部分双。至于为什么
my_log
泄漏:从您发布的代码中无法判断。为了导致泄漏,rake 任务中或规范本身中的某些代码需要将my_log
注入某些全局状态,像一个类变量。The reason that the error is saying that
MyLogger
is a double is because it is one. When you callexpect(my_log).to receive
orallow(my_log).to receive
, you transform the instance into a partial-double.As for why
my_log
is leaking: it's impossible to tell from the code that you posted. In order to cause a leak, some code either in your rake task or in the spec itself would need to be injectingmy_log
into some global state, like a class variable.通常,这种事情通常是由于在类变量中存储的东西而引起的。您将不得不弄清楚那是哪里,以及如何清除或避免使用类变量 - 它可以在您的班级或宝石中。
如果可能的话,使用类变量或外部系统会导致测试间问题的最佳实践是在测试之间清理这种事情。例如,
actionmailer :: base.deliveries
和rails.cache
是应该清除的常见事物。您还应清除Faker :: uniquegenerator
或requestStore
如果您使用这些宝石,我敢肯定还有更多。一旦找到了类变量,如果它在代码中,并且确定类变量是正确的方法,则可以将
reset
或clear
类方法添加到类并在 spec_helper.rb 或rails_helper.rb
中的 rspec块中以命名。
请注意,尽管很多事情都会在测试之间自动清除自己(例如RSPEC模拟),并且使您认为这都是自动的,但实际上,通常是什么。
测试只能通过(a)主要利用在测试中创建的对象,而仅利用在其中存储数据,并且(b)确保通过显式代码或负责任的GEM在测试之间清除其他任何内容。
在处理外部第三方系统时,这可能会特别烦人,这很少提供API来清除分期环境,因此,即使使用
vcr
GEM,有时也需要大量护理。Mostly commonly this sort of thing is caused by storing something in a class variable. You will have to figure out where that is, and how to clear it or avoid using a class variable - it could be in your class or in a gem.
Best practice, where using a class variable or an external system is causing inter-test issues, is to clean this sort of thing between tests, if possible. For example
ActionMailer::Base.deliveries
andRails.cache
are common things that should be cleared. You should also clearFaker::UniqueGenerator
orRequestStore
if you're using those gems, and I'm sure there are more.Once you have found the class variable, if it's in your code, and you have determined a class variable is the correct approach, you can add a
reset
orclear
class method to the class and call it in abefore(:each)
RSpec block in yourspec_helper.rb
orrails_helper.rb
.Note that while a lot of things will clear themselves automatically between tests (such as RSpec mocks), and make you think this is all automatic, in practice it is often anything but.
Tests will only remain independent by (a) mostly making use of objects created in the tests and mostly only storing data in there and (b) ensuring anything else is cleared between tests by your explicit code or within the responsible gem.
This can be especially annoying when dealing with external third-party systems, which rarely provide an API to clear a staging environment, and hence sometimes require considerable care even when using the
vcr
gem.