Quelle est la différence entre les méthodes build et create dans FactoryGirl?

95

L'introduction de Factory Girl fait la différence entre FactoryGirl.build()et FactoryGirl.create():

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

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

Je ne comprends toujours pas les différences pratiques entre les deux. Quelqu'un peut-il donner un exemple où vous voudriez utiliser l'un et pas l'autre? Merci!

Avery
la source

Réponses:

117

La create()méthode persiste l'instance du modèle tandis que la build()méthode la conserve uniquement en mémoire.

Personnellement, j'utilise la create()méthode uniquement lorsque la persistance est vraiment nécessaire car l'écriture dans DB prend du temps aux tests.

par exemple

Je crée des utilisateurs pour l'authentification avec create()parce que mon moteur d'authentification interroge la base de données.

Pour vérifier si un modèle a un attribut, la build()méthode le fera car aucun accès à la base de données n'est requis.

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

Mettre à jour

"Il y a une exception qui" crée "réellement lorsque vous construisez des associations, c'est-à-dire que votre association n'est plus en mémoire mais persiste. Gardez cela à l'esprit" - Shakes

Helio Santos
la source
16
Il y a une exception qui "crée" réellement lorsque vous construisez des associations, c'est-à-dire que votre association n'est plus en mémoire mais persistante. Gardez cela à l'esprit
Secoue le
@Shakes, je ne travaille plus dans les rails. Je vérifierai cela dès que possible.
Helio Santos
Quelqu'un a-t-il créé un outil pour remplacer chaque instance de createpar buildet l'annuler si le test échoue?
mgold le
Lit #createet renvoie- t- il l'objet persistant à partir du disque ou renvoie-t-il l'objet qui est en mémoire après l'avoir conservé? En d'autres termes, est-ce que faire est create(...)équivalent à create(...).reload?
Dennis
@mgold Vim est plutôt doué pour ce genre de choses.
Expiation limitée le
15

L'utilisation FactoryGirl.build(:factory_name)ne persiste pas dans la base de données et n'appelle pas save!, donc vos validations Active Record ne s'exécuteront pas. C'est beaucoup plus rapide, mais les validations peuvent être importantes.

L'utilisation FactoryGirl.create(:factory_name)persistera dans la base de données et appellera les validations d'enregistrement actif. Ceci est évidemment plus lent mais peut attraper des erreurs de validation (si vous vous en souciez dans vos tests).

gouffre
la source
11
Ou, vous pouvez simplement faire FactoryGirl.build (: nom_usine) .valid? qui exécutent des validations sans enregistrer dans la base de données.
jinavar1
1

FactoryGirl.create()créera un nouvel objet et des associations (si la fabrique en a) pour lui. Ils seront tous conservés dans une base de données. En outre, il déclenchera les validations du modèle et de la base de données. Rappels after(:build)et after(:create)seront appelés après la sauvegarde de l'usine. Sera également before(:create)appelé avant la sauvegarde de l'usine.

FactoryGirl.build()ne sauvera pas un objet, mais fera toujours des requêtes à une base de données si la fabrique a des associations. Il déclenchera des validations uniquement pour les objets associés. Le rappel after(:build)sera appelé après la construction de l'usine.

Notez que dans la plupart des cas, lorsque vous testez des modèles, il est préférable d'utiliser build_stubbedpour de meilleures performances. En savoir plus ici .

Nesha Zoric
la source