При написании функциональных тестов для контроллера я столкнулся со сценарием, в котором у меня есть фильтр before_filter, запрашивающий некоторую информацию из базы данных, которая требуется для одного из моих тестов. Я использую Factory_girl для генерации тестовых данных, но я хочу избежать попадания в базу данных, когда это явно не нужно. Я также хотел бы избежать тестирования моего метода before_filter здесь (я планирую протестировать его в отдельном тесте). Насколько я понимаю, насмешка/заглушка - это способ добиться этого.
Мой вопрос заключается в том, как лучше всего имитировать/заглушить этот метод в этом сценарии.
Мой метод перед фильтром ищет сайт в базе данных на основе поддомена, найденного в URL-адресе, и устанавливает переменную экземпляра, которая будет использоваться в контроллере:
#application_controller.rb
def load_site_from_subdomain
@site = Site.first(:conditions => { :subdomain => request.subdomain })
end
Мой контроллер, использующий этот метод в качестве фильтра before_filter:
# pages_controller.rb
before_filter :load_site_from_subdomain
def show
@page = @site.pages.find_by_id_or_slug(params[:id]).first
respond_to do |format|
format.html { render_themed_template }
format.xml { render :xml => @page }
end
end
Как видите, это зависит от установки переменной @site
(с помощью фильтра before_filter). Однако во время тестирования я хотел бы, чтобы тест предполагал, что @site
был установлен и что у него есть по крайней мере 1 связанная страница (найденная @site.pages
). Затем я хотел бы протестировать свой метод load_site_from_subdomain
позже.
Вот что у меня есть в моем тесте (с использованием Shoulda & Mocha):
context "a GET request to the #show action" do
setup do
@page = Factory(:page)
@site = Factory.build(:site)
# stub out the @page.site method so it doesn't go
# looking in the db for the site record, this is
# used in this test to add a subdomain to the URL
# when requesting the page
@page.stubs(:site).returns(@site)
# this is where I think I should stub the load_site_from_subdomain
# method, so the @site variable will still be set
# in the controller. I'm just not sure how to do that.
@controller.stubs(:load_site_from_subdomain).returns(@site)
@request.host = "#{ @page.site.subdomain }.example.com"
get :show, :id => @page.id
end
should assign_to(:site)
should assign_to(:page)
should respond_with(:success)
end
Это оставляет меня с ошибкой в результатах моего теста, говорящей мне, что @site
равно нулю.
Я чувствую, что иду по этому пути неправильно. Я знаю, что было бы легко просто создать сайт Factory.create, чтобы он существовал в базе данных, но, как я уже говорил ранее, я хотел бы уменьшить использование базы данных, чтобы ускорить мои тесты.