По хардкору: instance_double, verify_partial_doubles
В комментариях к посту о дублерах, стабах и моках Макс Прокопьев упомянул instance_double
, секретную технику старших разработчиков. О ней и поговорим. Коротко, по делу и с примерами.
Ситуация
Возьмем пример с Notifications
:
class Notifications
def as_json
# Загружаем и отдаем последние новости
# и уведомления с серверов Юрия Лозы по ХТТП
end
end
class NotificationsController
def index
# Оборачиваем уведомления в ключ 'data'
render json: { data: notifications.as_json }
end
def notifications
Notifications.new
end
end
Чтобы не обращаться к серверам Лозы в тестах, используем дублера:
describe "NotificationsController#index" do
let(:notifications) do
double(:datasource, as_json: { notifications: [] })
end
before do
allow(Notifications)
.to receive(:new)
.and_return(notifications)
end
it "wraps notifications in 'data' key" do
get :index, format: :json
expect(json_response["data"].keys)
.to have_key "notifications"
end
end
Что произойдет, если мы переименуем Notifications#as_json
в Notifications#to_json
? Ничего. Мы останемся наедине с зеленым тестом, проверяющим бесполезного дублера.
instance_double
Чтобы не попадать в такую дебильную ситуацию, используйте instance_double
:
describe 'NotificationsController#index' do
let(:notifications) do
instance_double(Datasource, as_json: { notifications: [] })
end
# ...
end
Такой дублер проверит свой интерфейс. Если метода нет или у него другие аргументы — красный тест.
Чтобы так же проверять моки и стабы, убедитесь, что verify_partial_doubles
включен в spec_helper.rb
.
Внимательный читатель со звездочкой наверняка заметил, что одного instance_double
мало. Все верно. В RSpec есть похожие дублеры для классов, модулей и объектов: object_double
и class_double
.
P. S. Ещё больше постов о программировании, тестах и культуре разработки у меня в Телеграме.