Pregunta

Al escribir pruebas funcionales de un controlador, me encontré con un escenario en el que tengo una before_filter solicitar alguna información de la base de datos que una de mis pruebas requiere. Estoy usando factory_girl para generar datos de prueba, pero quiero evitar golpear la base de datos cuando no es necesario de forma explícita. También me gustaría evitar ensayos mi método before_filter aquí (tengo la intención de probarlo en un ensayo separado). Según tengo entendido, burlándose / stubbing es la manera de lograr esto.

Mi pregunta es, ¿cuál es la mejor manera de burlarse / ramal este método en este escenario.

Mi antes de miradas método de filtro para un sitio en el PP sobre la base de un subdominio encuentra en la URL y establece una variable de instancia para ser utilizado en el controlador:


#application_controller.rb

def load_site_from_subdomain
  @site = Site.first(:conditions => { :subdomain => request.subdomain })
end

Mi controlador que utiliza este método como una 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

Como se puede ver, se basa en la variable @site ser establecido (por el before_filter). Durante las pruebas, sin embargo, me gustaría tener la prueba de que asuma @site ha sido ajustada, y que tiene al menos 1 página asociada (encontrado por @site.pages). Quisiera a continuación, probar mi método load_site_from_subdomain más tarde.

Esto es lo que tengo en mi prueba (utilizando Shoulda y 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

Esto me deja con un error en los resultados de mi prueba me dice que @site es nula.

Me siento como si me fuera de este por el camino equivocado. Sé que sería fácil simplemente Factory.create el sitio por lo que existe en el PP, pero como he dicho antes, me gustaría reducir el uso db para ayudar a mantener mis pruebas rápida.

¿Fue útil?

Solución

Trate apagando 'Site.first', ya que el ajuste de la var @site que es necesario talón y no var regresar de la before_filter.

Otros consejos

La razón por la que su @site es nil porque su load_site_from_subdomain hace la asignación de valor para @site - no devuelve ningún valor, por tanto, su stubbing para load_site_from_subdomain simplemente no asigna el valor a @site. Hay dos soluciones temporales para esto:

Primera forma:

Cambiar load_site_from_subdomain hacer sólo un valor de retorno:

def load_site_from_subdomain
  Site.first(:conditions => { :subdomain => request.subdomain })
end

y luego retire la before_filter :load_site_from_subdomain y cambiar su show a:

def show
  @site = load_site_from_subdomain
  @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

Y luego hacer el tropezar en la prueba:

@controller.stubs(:load_site_from_subdomain).returns(@site)

asegurar que nuestra @site se apagó indirectamente a través de load_site_from_subdomain

Segundo manera

Para derivadas La Site.first, en realidad no me gusta este enfoque como en la prueba de funcionamiento, que en realidad no importa cómo se recupera el modelo, pero el comportamiento de la respond. De todos modos, si se siente como ir este camino, podría código auxiliar que en su prueba:

Site.stubs(:first).returns(@site)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top