Я использую clear ruby (ruby 2.3.5) без Rails и ActiveRecord и пытаюсь написать спецификации для некоторого сервиса. И если я запускаю только часть файла (включая спецификацию проблемы), он проходит. Если я запускаю весь файл - спецификация проблемы не удалась.
Кстати, я уже использую rspec / retry, и он 20 раз повторяет настройки (и я вижу в журналах, что спецификация проблемы не удаласьвсего 20 раз).
ballot_spec.rb
# frozen_string_literal: true
require 'spec_helper'
require 'byebug'
RSpec.describe Ballot do
describe '#run' do
let(:kingdoms) { build_list(:kingdom, 6) }
let(:service) { described_class.new(kingdoms) }
before { allow(service).to receive(:hold_ballot) }
it 'holds ballot if cannot_finish_ballot? returns true' do
allow(service).to receive(:cannot_finish_ballot?).and_return(true)
service.run
expect(service).to have_received(:hold_ballot).at_least(:once)
end
it "doesn't hold ballot if cannot_finish_ballot? returns false" do
allow(service).to receive(:cannot_finish_ballot?).and_return(false)
service.run
expect(service).not_to have_received(:hold_ballot)
end
it 'returns Struct object' do
expect(service.run.class.superclass).to be Struct
end
end
describe '#hold_ballot' do
let(:all_kingdoms) { build_list(:kingdom, rand(2..10)) }
let(:pretendents) { all_kingdoms.first(rand(2..all_kingdoms.count)) }
let(:message) { build(:message, from: all_kingdoms.sample, to: all_kingdoms.sample) }
let(:expected_message_count) { pretendents.count * all_kingdoms.count }
let(:new_service) { described_class.new(pretendents) }
before do
allow(Message).to receive(:new).and_return(message)
allow(message).to receive(:send)
new_service.send('hold_ballot')
end
\/\/ THE PROBLEM IS IN THIS SPEC \/\/
it 'prepares messages to all existed kingdoms from every pretendent' do
expect(Message).to have_received(:new).exactly(expected_message_count).times
end
it 'only 6 of messages will be selected to be sent' do
expect(message).to have_received(:send).exactly(6).times
end
it 'resets Kingdoms' do
allow(Kingdom).to receive(:reset)
new_service.run
expect(Kingdom).to have_received(:reset).at_least(:once)
end
end
end
при запуске rspec spec / services / ballot_spec.rb: 26 (для теста всего метода '#hold_ballot') каждая спецификацияпрошло. когда я запускаю rspec spec / services / ballot_spec.rb, у меня возникает ошибка:
1) Ballot#hold_ballot prepares messages to all existed kingdoms from every pretendent
Failure/Error: expect(Message).to have_received(:new).exactly(expected_message_count).times
(Message (class)).new(*(any args))
expected: 4 times with any arguments
received: 260 times with any arguments
когда я использую byebug, я вижу, что в классе Kingdom есть десятки объектов, но есть переменные "all_kingdoms" и "pretendents"содержит не более 10 объектов.
Итак, единственная корневая причина, которую я вижу здесь - rspec не очищает королевства, созданные во время тестирования метода "#run", но как заставить его уничтожить их? Я не использую ActiveRecord, не использую Rails, поэтому не могу настроить "перезагрузить!"или "уничтожить" явно. Пытался запустить GC.start, но это не помогает. Что я могу сделать? Большое спасибо! )
spec_helper.rb
# frozen_string_literal: true
require './models/kingdom.rb'
require './models/message.rb'
require './services/message_compose.rb'
require 'factory_bot'
require 'ffaker'
require 'capybara'
require 'rspec/retry'
require './spec/factories/kingdom.rb'
require './spec/factories/message.rb'
RSpec.configure do |config|
config.verbose_retry = true
config.display_try_failure_messages = true
config.around :each do |ex|
ex.run_with_retry retry: 20 unless ex.run_with_retry
end
config.include FactoryBot::Syntax::Methods
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
end