2011-02-28 14 views
17

Esto ha causado un poco de frustración recientemente ...AssociationTypeMismatch y factorygirl

Parece que el uso de fábricas en mis pruebas de pepino, en algunas situaciones provoca errores AssociationTypeMismatch como:

MyModel (# 65776650) que se espera, Obtuve MyModel (Nº 28190030) (ActiveRecord :: AssociationTypeMismatch)

Parece que esto sucede cuando hay una referencia de asociación, como si el objeto creado en fábrica fuera diferente del real. Consulte esta pregunta para obtener más detalles: Cucumber duplicate class problem: AssociationTypeMismatch

He estado cambiando gradualmente las llamadas a las fábricas a las llamadas reales Model.create o mock_model. Sería bueno seguir usando Factory girl ... Me pregunto si hay algo que haya hecho mal.

Gracias

+2

Tenga en cuenta que esto también puede ocurrir si utiliza 'reload!' En una ventana de consola y luego continúa creando Fábricas. La solución es solo para reiniciar su sesión de consola. –

+0

La solución sobre no tener que usar 'recargar!' Mencionado por @ Chrisbloom7 funciona. Sólo un poco de dolor para mantener el reinicio de la consola de rieles –

Respuesta

4

parece suceder si ActiveSupport descarga y vuelve a cargar una constante que tiene una referencia a. que he experimentado lo mismo con Rspec/capibara, y lo ayudó fue una mezcla de cosas diferentes:

  • Asegúrese de que tiene cached_classes establece en false en el entorno de prueba (config/ambientes/test.rb)
  • En sus gemspec, intente reemplazar requiere factory_girl_rails '' con 'factory_girl'

estoy usando Spork (un servidor de prueba), que parece hacer esto cada vez más difícil. Si está utilizando un servidor de prueba, evalúe si debe colocar ',: require => false' después de factory_girl en su gemspec.

El tema también se trata en this google groups thread

Por favor, háganos saber si algo de esto ayudó.

1

I tenido cierto éxito con la recarga de las definiciones de fábrica intentar algo como esto:

class Factory 
    def self.reload_definitions #:nodoc: 
    self.factories.clear 
    definition_file_paths.each do |path| 
     load("#{path}.rb") if File.exists?("#{path}.rb") 

     if File.directory? path 
     Dir[File.join(path, '*.rb')].each do |file| 
      load file 
     end 
     end 
    end 
    end 
end 
8

Tenía este pasa a mí con rieles 3.1.0 RC5, y tengo trabajo.

Para ampliar la respuesta de Jonas.

debe cambiar su Gemfile que ser así:

gem 'factory_girl', '~> 2.0.0', :require => false 
gem 'factory_girl_rails', '~> 1.1.0', :require => false 

Y entonces, si usted está utilizando Spork, hace su spec/spec_helper.rb mirada archivo de la siguiente manera:

Spork.each_run do 
require 'factory_girl' 
require 'factory_girl_rails' 
end 
+3

También tuve que poner esto en mi Spork.each_run (antes de lo requerido) para que funcione: ActiveSupport :: Dependencies.clear #Reload models – NotDan

+0

Muchas gracias. factory_girl es requerido por factory_girl_rails explícitamente. Así que 'gem 'factory_girl_rails'' y' require' factory_girl_rails'' deberían ser suficientes. – iltempo

2

Esto sucede porque cache_classes es falso, como requiere Spork. El carpincho vuelve a cargar las clases de Rails para cada solicitud (o, para ser correctos, el middleware de reubicación de Rails lo hace, lo cual no se llama para las pruebas normales), y esto desconcierta a las fábricas (exactamente por qué, no estoy seguro). Puede volver a cargarlos o simplemente ejecutar sus especificaciones de Carpincho fuera de Spork.

Así que necesita dos cosas: ejecutar Capybara solo fuera de Spork, y establecer cache_classes en falso solo para Spork.

sólo para ejecutar Carpincho exterior de Spork, tengo un Guardfile que corre especificaciones en spec/solicitudes fuera de Spork y otras especificaciones en el interior de Spork aquí:

https://gist.github.com/1731900

Luego, en config/environments/test.rb:

config.cache_classes = !ENV['DRB'] 

Sus especificaciones de Capybara serán un poco más lentas, ya que necesitan arrancar los rieles, pero todo funcionará.

4

Si está utilizando Spork, asegúrese de volver a cargar sus fábricas después de volver a cargar sus modelos.

E.g.

Spork.each_run 
    if Spork.using_spork? 
    print "Reloading models ... " 
    ActiveSupport::Dependencies.clear 
    puts "done" 

    print "Reloading factories ... " 
    FactoryGirl.reload 
    puts "done" 
    end 
end 
0

Me encontré con este mismo problema y pasé probablemente diez horas probando cada solución en este hilo y en cualquier otro lugar en la web. Empecé a arrancar grandes trozos de código tratando de acercarlo a otra aplicación mía en la que no podía reproducir el problema. Por último, me encontré con algunas funciones de ayuda en mi archivo spec_helper:

def sign_in(user)    
    visit signin_path    
    fill_in "Email", with: user.email 
    fill_in "Password", with: user.password 
    click_button "Sign in"  

    # Sign in when not using Capybara as well. 
    cookies[:remember_token] = user.remember_token if defined?(cookies) 
end 

Un ayudante sign_in la intención de trabajar tanto en el controlador y de solicitud de especificaciones. Y lo hace, más o menos, simplemente no con spork. Cuando quité los ayudantes capibara se resolvió el problema:

def sign_in(user)    
    cookies[:remember_token] = user.remember_token 
end 
1

me encontré con este problema cuando pasé la opción "clase" a mi fábrica que fue heredado por otras fábricas:

factory :draft_resource, :class => Resource do 

factory :resource, :parent => :draft_resource do 

El único La solución que pude encontrar fue simplemente no hacer esto.

Cuestiones relacionadas