¿Cuál es la diferencia entre los métodos de construcción y creación en FactoryGirl?

95

La introducción de Factory Girl delinea la diferencia entre FactoryGirl.build()y FactoryGirl.create():

# Returns a User instance that's not saved
user = FactoryGirl.build(:user)

# Returns a saved User instance
user = FactoryGirl.create(:user)

Todavía no entiendo las diferencias prácticas entre los dos. ¿Alguien puede dar un ejemplo en el que le gustaría usar uno y no el otro? ¡Gracias!

Avery
fuente

Respuestas:

117

El create()método conserva la instancia del modelo mientras que el build()método la mantiene solo en la memoria.

Personalmente, uso el create()método solo cuando la persistencia es realmente necesaria, ya que escribir en DB hace que las pruebas consuman mucho tiempo.

p.ej

Creo usuarios para la autenticación create()porque mi motor de autenticación consulta la base de datos.

Para verificar si un modelo tiene un atributo, el build()método servirá porque no se requiere acceso a la base de datos.

it{Factory.build(:user).should respond_to(:name)}

Actualizar

"Hay una excepción que la construcción realmente 'crea' cuando está construyendo asociaciones, es decir, su asociación ya no está en la memoria sino que persiste. Téngalo en cuenta" - Shakes

Helio Santos
fuente
16
Hay una excepción que build realmente 'crea' cuando está construyendo asociaciones, es decir, su asociación ya no está en la memoria sino que persiste. Tenlo en cuenta
Shakes
@Shakes, ya no trabajo en rieles. Lo comprobaré tan pronto como pueda.
Helio Santos
¿Alguien ha creado una herramienta para reemplazar cada instancia de createcon buildy deshacerla si la prueba falla?
mgold
¿ #createLee y devuelve el objeto persistente del disco, o devuelve el objeto que está en la memoria después de persistirlo? En otras palabras, ¿es hacer create(...)equivalente a create(...).reload?
Dennis
@mgold Vim es bastante bueno en ese tipo de cosas.
Expiación limitada
15

El uso FactoryGirl.build(:factory_name)no persiste en la base de datos y no llama save!, por lo que las validaciones de Active Record no se ejecutarán. Esto es mucho más rápido, pero las validaciones pueden ser importantes.

El uso FactoryGirl.create(:factory_name)persistirá en la base de datos y llamará a las validaciones de Active Record. Obviamente, esto es más lento, pero puede detectar errores de validación (si le importan en sus pruebas).

abismo
fuente
11
O bien, podría simplemente hacer FactoryGirl.build (: factory_name) .valid? que ejecutan validaciones sin guardar en la base de datos.
jinavar1
1

FactoryGirl.create()creará nuevos objetos y asociaciones (si la fábrica tiene alguna) para él. Todos se conservarán en una base de datos. Además, activará validaciones tanto del modelo como de la base de datos. Devuelve la llamada after(:build)y after(:create)se llamará después de que se guarde la fábrica. También before(:create)se llamará antes de que se guarde la fábrica.

FactoryGirl.build()no guardará un objeto, pero aún hará solicitudes a una base de datos si la fábrica tiene asociaciones. Activará validaciones solo para objetos asociados. La devolución de after(:build)llamada se llamará después de que se construya la fábrica.

Tenga en cuenta que, en la mayoría de los casos, es mejor utilizar modelos de prueba build_stubbedpara un mejor rendimiento. Lea más sobre esto aquí .

Nesha Zoric
fuente