2010-10-28 11 views
8

Tengo las siguientes fábricas:error Factory Girl con relación has_many

Factory.define :email do |email| 
    email.email {"infomcburney.cowan.com"} 
end 

Factory.define :lead do |lead| 
    lead.emails {|emails| [emails.association(:email)]} 
end 

Qué está modelando las siguientes clases

class Lead < ActiveRecord::Base 
    has_many :emails 
end 

class Email < ActiveRecord::Base 
    belongs_to :lead, :class_name => "Lead", :foreign_key => "lead_id" 
end 

Cuando ejecuto el presente ensayo a través de la debería:

should "capture emails" do 
     lead = Factory.build(:lead) 
     assert_equal(1, lead.emails.size) 
    end 

me sale el siguiente error:

Factory::AttributeDefinitionError: Attribute already defined: emails

estoy completamente atascado en esto, alguien me puede apuntar en la dirección correcta. Estoy usando factory_girl 1.3.2.

+0

Punto de estilo: las fábricas deben contener datos de marcador de posición y nada más. Todo lo que debería importarle al usarlos es que se genere una ventaja válida, y debe suponer que la cantidad real de correos electrónicos conectados al cliente potencial está sujeta a cambios. Si su prueba depende de una cierta cantidad de clientes potenciales, construya el cliente potencial de fábrica y configure los correos electrónicos explícitamente. – Matchu

Respuesta

9

recomendaría en contra de añadir datos de relaciones has_many a sus fábricas. La razón de esto es que su fábrica de plomo ahora depende de poblar esta asociación y está agregando más acoplamiento y potencialmente algo de confusión en el futuro si la asociación cambia.

Si quieres probar esta relación (y te recomiendo que lo hagas), hay una gran gema llamada Shoulda que agrega macros de prueba unitarias para garantizar que las relaciones se configuren correctamente. Yo no lo he utilizado con el construido en los carriles Test :: Unidad, pero un ejemplo RSpec sería algo como:

describe Lead do 
    it { should have_many(:emails) } 
end 

Si realmente quiere poner a prueba esta relación, debe hacerlo en la especificación. Retire la asociación mensajes de correo electrónico desde su fábrica de plomo y crear un objeto de plomo y tratar de pasar un par de objetos de correo de este modo:

lead = Factory.build(:lead) 
2.times do { lead.emails << Factory.build(:email, :lead => lead) } 

entonces debería haber una asociación par de correos electrónicos con él. Sin embargo, debe confiar en ActiveRecord y simplemente probar cosas que van más allá de lo que Rails ya está haciendo por usted. Aquí es donde entra en juego Shoulda.

Otro comentario que tengo es en su correo electrónico belongs_to relación. Como solo está utilizando las convenciones predeterminadas, los rieles sabrán qué hacer.

class Email < ActiveRecord::Base 
    belongs_to :lead 
end 
+0

Gracias por su respuesta, pero lo que si quiero una fábrica llamada lead_with_one_email porque siempre estoy teniendo para crearlo como usted está haciendo arriba? Seguramente tiene sentido poder hacerlo en la fábrica para reducir la repetición del código de creación. Parece que esto debería ser posible? – dagda1

+0

Si todas sus pruebas de plomo requieren al menos un correo electrónico, entonces este es un problema. Debería poder probar su modelo de plomo independientemente de cualquier otro modelo. Es posible que deba usar simulaciones y talones para esto. Sin embargo, si solo tiene un subconjunto de pruebas que desea probar con un correo electrónico, crearía un grupo que aislaría este comportamiento.En Rspec, este grupo se denomina bloque de descripción o de contexto y aísla algunas pruebas que requieren una configuración específica (como un correo electrónico). –

Cuestiones relacionadas