Как вы имитируете отсутствующий ключ I18n в тесте Rspec? У меня есть помощник, который ищет использовать ключ I18n, если он доступен. Я не знаю, как создать тестовый случай, когда он недоступен. Основываясь на консольном тестировании, я почти уверен, что вспомогательный метод правильный, но я не знаю, как построить тест на основе этого результата (когда не установлены все три возможных типа заголовков).

# app/helpers/application_helper.rb

def available_page_title
  title = ""
  case
  when content_for?(:page_title)
    title = content_for(:page_title)
  when !@page_title.nil?
    title = @page_title
  when I18n.exists?('page_title.default')
    title = t('page_title.default')
  end
end

-

# config/locales/en.yml

en:
  page_title:
    delimiter: ' - '
    default: Default Page Title
    admin_namespace: 'Admin'


# spec/helpers/application_helper.rb
describe 'available_page_title' do
  it '(1) returns the the translation title if no other titles set' do
    allow(I18n).to receive(:t).with('page_title.default').and_return("Test Title from i18n")
    @page_title = nil
    expect(helper.available_page_title).to eq(t('page_title.default'))
  end

  it '(2) returns the the @page_title if it exists and no content_for exists' do
    allow(I18n).to receive(:t).with('page_title.default').and_return("Test Title from i18n")
    translation_title = t('page_title.default')
    @page_title = "Test Title from @page_title"
    expect(helper.available_page_title).to eq(@page_title)
  end

  it '(3) returns the the content_for title if it exists' do
    allow(I18n).to receive(:t).with('page_title.default').and_return("Test Title from i18n")
    translation_title = t('page_title.default')
    @page_title = "Test Title from @page_title"
    helper.content_for(:page_title, 'Test Title from content_for')
    expect(helper.available_page_title).to eq('Test Title from content_for')
  end

  it '(4) returns a blank string if no titles are found' do
    # Things I've tried...
    # I18n.backend.store_translations(:en, { page_title: { default: '' }})
    # I18n.backend.store_translations(:en)
    # I18n.backend.store_translations(:en, { nil })
    # I18n.backend.store_translations()
    # I18n.backend = I18n::Backend::Simple.new
    allow(I18n).to receive(:t).with('page_title.default').and_return(nil)
    @page_title = nil
    expect(helper.available_page_title).to eq('')
  end
end

Вот результаты теста:

$ bundle exec rspec spec/helpers/application_helper_spec.rb:130
Run options: include {:locations=>{"./spec/helpers/application_helper_spec.rb"=>[130]}}

Randomized with seed 14478

ApplicationHelper
  available_page_title
    (3) returns the the content_for title if it exists
    (1) returns the the translation title if no other titles set
    (2) returns the the @page_title if it exists and no content_for exists
    (4) returns a blank string if no titles are found (FAILED - 1)

Failures:

  1) ApplicationHelper available_page_title should (4) return a blank string if no titles are found
     Failure/Error: expect(helper.available_page_title).to eq('')

       expected: ""
            got: "Default Page Title"

       (compared using ==)
     # ./spec/helpers/application_helper_spec.rb:160:in `block (3 levels) in <top (required)>'

Finished in 0.69197 seconds (files took 4.32 seconds to load)
4 examples, 1 failure

Failed examples:

rspec ./spec/helpers/application_helper_spec.rb:152 # ApplicationHelper available_page_title should (4) return a blank string if no titles are found

Randomized with seed 14478

Обновление 2017-05-31

Ответ @ gwcodes немного помог, но по-прежнему не правильно настроил тест.

allow(I18n).to receive(:translate).with('page_title.default').and_return(nil)

Используя эту строку, тест настраивается таким образом, чтобы на самом деле еще был ключ page_title.default, но его значение равно нулю. Это не полезно.

Мой вспомогательный метод проверяет наличие ключа. Вот результат вывода текущей тестовой ситуации:

[5] pry(#<RSpec::ExampleGroups::ApplicationHelper::AvailablePageTitle>)> I18n.translate('page_title.default')
=> nil
[6] pry(#<RSpec::ExampleGroups::ApplicationHelper::AvailablePageTitle>)> I18n.exists?('page_title.default')
=> true
[7] pry(#<RSpec::ExampleGroups::ApplicationHelper::AvailablePageTitle>)> I18n.t('page_title.default').empty?
=> false

Так что вопрос до сих пор остается. Как настроить тестовую среду так, чтобы проверка на наличие ключа I18n возвращала ложь?

1
Robert Travis Pierce 28 Май 2017 в 05:33

2 ответа

Лучший ответ

Я думаю использовать ваше первое решение в общем контексте.

# spec/support/i18n_stubs.rb

RSpec.shared_context 'i18n stubs' do
  def stub_i18n_value_with_nil(key)
    allow(I18n).to receive(:t).with(key).and_return(nil)
    allow(I18n).to receive(:exists?).with(key).and_return(false)
  end
end

Затем добавьте require support/i18n_stubs в ваш файл вспомогательных функций. Внутри, где это нужно вашему файлу спецификаций, вы можете просто поместить include_context 'i18n stubs' и вызвать stub_i18n_value_with_nil('some.i18n.key') перед выполнением утверждений.

Например в спецификации файла:

require 'spec_helper'

RSpec.describe 'some_file_or_class' do
  include_context 'i18n stubs'

  describe 'available_page_title' do
    context 'when i18n key is not present' do
      before(:each) do
        stub_i18n_value_with_nil('some.i18n.key')
      end

      it 'returns blank string' do
        # do assertion here
      end
    end
  end
end
2
baskara 3 Июн 2017 в 19:30

Я придумал решение, оформив бэкэнд I18n для тестирования (хотя это немного похоже на подход с шариковым молотком).

Я создал spec / support / i18n_simple_stub.rb:

module I18n
  module Backend
    class SimpleStub
      def exists?(key, *args)
        false
      end
    end
  end
end

И затем установите бэкэнд в этом (ранее не пройденном) тесте. Вот новый тест:

it '(4) returns a blank string if no titles are found' do
  # Sets exists? method to false
  I18n.backend = I18n::Backend::SimpleStub.new 
  @page_title = nil
  expect(helper.available_page_title).to eq('')
end

Если у кого-то есть лучший метод, я бы с удовольствием его услышал и изучил.

0
Robert Travis Pierce 1 Июн 2017 в 01:02