Как использовать RSpec для тестирования кода с безопасной навигацией Ruby &.оператор? - PullRequest
0 голосов
/ 01 февраля 2019

Я хотел бы написать модульный тест для кода этой формы:

class Foo
  def bar(obj)
    return nil unless obj&.foo
    obj.bar
  end
end

Вот пример теста:

RSpec.describe Foo do
  subject { Foo.new.bar(obj) }

  context 'when obj is nil' do
    let(:obj) { nil }

    it 'does not call :foo' do
      expect(obj).to_not receive(:foo)
      subject
    end
  end
end

Этот код возвращает:

Failures:

  1) Foo when obj is nil does not call :foo
     Failure/Error: expect(obj).to_not receive(:foo)
       An expectation of `:foo` was set on `nil`. To allow expectations on `nil` and suppress this message, set `RSpec::Mocks.configuration.allow_message_expectations_on_nil` to `true`. To disallow expectations on `nil`, set `RSpec::Mocks.configuration.allow_message_expectations_on_nil` to `false`

По умолчанию RSpec 3.x жалуется при установке ожидания на nil.У меня большая база кода, поэтому я не могу изменить этот глобальный параметр, чтобы упростить тестирование такого рода кода.Глобальные изменения могут вызвать проблемы у других разработчиков.

Я знаю, что могу изменить код на что-то вроде return nil unless obj.present? && obj.foo, но мне особенно любопытно работать с оператором безопасной навигации.Много гуглинга поднял zippo на эту тему.

Есть идеи?

1 Ответ

0 голосов
/ 01 февраля 2019

Не самый чистый способ, но, по крайней мере, сработает ожидание нулевого значения до теста и повторное его отключение после этого.Таким образом, изменяя спецификацию на

RSpec.describe Foo do
  subject { Foo.new.bar(obj) }

  context 'when obj is nil' do
    let(:obj) { nil }

    before do 
      RSpec::Mocks.configuration.allow_message_expectations_on_nil = true
    end

    after do 
      RSpec::Mocks.configuration.allow_message_expectations_on_nil = false
    end

    it 'does not call :foo' do
      expect(obj).to_not receive(:foo)
      subject
    end
  end
end

Если это повторяющийся шаблон, можно также поместить его до и после блока внутри макроса rspec (context 'when obj is nil', nil_mock: true do).

Однако я неконечно, если оно того стоит, так как при работе с этими глобальными настройками есть побочные эффекты, которые могут привести к ошибкам, зависящим от порядка, которые потом сложно отладить.Кроме того, я бы на самом деле только проверял, была ли вызвана foo, когда она является командой, то есть она изменяет состояние системы и, как таковая, имеет побочные эффекты.Если он просто обращается к переменной или вычисляет значение и, как таковой, не имеет побочных эффектов, я бы вообще не стал тестировать вызов и вместо этого сосредоточился бы на тестировании ввода и вывода тестируемого метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...