Rspec - можно ли заглушить хеш - PullRequest
0 голосов
/ 06 марта 2019

Я работаю над некоторыми юнит-тестами.Один из них использует определенную переменную конфигурации, установленную в моем приложении MyBigApp::Env, которая выглядит следующим образом:

{:country=>'uk', :another_hosts=>["192.168.99.105"]}

Поэтому я обращаюсь к ней с помощью MyBigApp::Env.country

Однаков моем модульном тесте я хочу, чтобы country для теста стал чем-то.

Используя rspec, я видел заглушку, но не могу заставить ее работать - любые идеи, где я ошибаюсь:

MyBigApp::Env.stub(:[]).with('country').and_return('gr')

Также пробовал это (как показано выше, устарел):

allow(MyBigApp::Env).to receive('country').and_return('gr')

Фактически в качестве теста, я также пытался:

my_hash = {:uri=>nil}
allow(my_hash).to receive(:[]).with(:uri).and_return('Over written!')
p my_hash

и это тоже не обновилось - он просто вернул {:uri=>nil}

В качестве обходного пути, в данный момент я должен сохранить env var во временной переменной в блоке before(each)верните его обратно в оригинал в after(each).Это очень рискованно для меня.Я думаю, представьте, что служба работает, и кто-то запускает модульные тесты, это может повлиять на конечного пользователя в этом маленьком экземпляре, когда выполняется тест.

Любая помощь будет оценена.

Спасибо

Ответы [ 3 ]

1 голос
/ 06 марта 2019

Да, это возможно, но имейте в виду, что заглушка работает, только когда вы запускаете / вызываете метод, который вы заглушали / высмеивали

my_hash = {:uri=>nil}
allow(my_hash).to receive(:[]).with(:uri).and_return('Over written!')
p my_hash[:url] # it will be 'Over written!'
0 голосов
/ 06 марта 2019

Просто хотел предложить альтернативу.Например:

def code_under_test
  key = 'country'

  # ... maybe lots of code

  value = MyBigApp::Env[key] # deep inside some classes

  # ... lots more code

  "This is the #{value}"
end

MyBigApp::Env жестко запрограммирован глубоко в коде, и необходимость в заглушке показывает, что зависимость и преимущества инкапсуляции ООП теряются.

It 'было бы намного проще, если бы это было так:

def code_under_test(config_vars = MyBigApp::Env)
  "This is the #{config_vars['country']}"
end

it 'should return my country value' do
  value = previous_code_under_test('country' => 'TEST VALUE')
  expect(value).to eq("This is the TEST VALUE")
end

Не требуется заглушки, просто вызовы старых методов.

0 голосов
/ 06 марта 2019

Это работает для меня:

my_hash = {:uri=>nil}
allow(my_hash).to receive(:[]).with(:uri).and_return('Over written!')
expect(my_hash[:uri]).to eq "Over written!"

В вашем тестовом примере вы просто вызываете p my_hash, который на самом деле не вызывает метод [].

С точки зрения того, почему это не работает с MyBigApp::Env, это действительно зависит от того, к какому классу это относится. Возможно любой метод .country на самом деле не вызывает [].

Действительно, если вы позвоните MyBigApp::Env['country'] и заглушке MyBigApp::Env, чтобы получить [] с 'country', должно работать.

Что касается вашего беспокойства по поводу изменения поведения запущенного приложения по сравнению с тестами ... что это за тесты ?! Выполнение юнит-тестов в реальном производственном приложении было бы очень странным. Как вы думаете, это изменит код вашего рабочего приложения? Хэш Env просто живет в памяти, верно?

В любом случае, вам никогда не придется беспокоиться о том, что ваши тесты изменят работу «конечного пользователя». Всегда запускайте тесты в полностью изолированном состоянии, то есть не используйте одну и ту же базу данных. На самом деле тестовая база данных обычно стирается после каждого теста.

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