Qual é a diferença entre os métodos de construção e criação no FactoryGirl?

94

A introdução da Factory Girl delineia a diferença entre FactoryGirl.build()e FactoryGirl.create():

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

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

Ainda não entendo as diferenças práticas entre os dois. Alguém pode dar um exemplo onde você gostaria de usar um e não o outro? Obrigado!

Avery
fonte

Respostas:

116

O create()método persiste a instância do modelo enquanto o build()método a mantém apenas na memória.

Pessoalmente, eu uso o create()método apenas quando a persistência é realmente necessária, uma vez que escrever no banco de dados torna os testes demorados.

por exemplo

Eu crio usuários para autenticação create()porque meu mecanismo de autenticação consulta o banco de dados.

Para verificar se um modelo tem um atributo, o build()método fará porque nenhum acesso ao banco de dados é necessário.

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

Atualizar

"Há uma exceção que o build realmente 'cria' quando você está construindo associações, ou seja, sua associação não está mais na memória, mas é persistente. Mantenha isso em mente" - Shakes

Helio Santos
fonte
14
Há uma exceção que o build realmente 'cria' quando você está construindo associações, ou seja, sua associação não está mais na memória, mas é persistente. Tenha isso em mente
Shakes
@Shakes, não trabalho mais com trilhos. Vou verificar isso assim que puder.
Helio Santos
Já alguém fez uma ferramenta para substituir cada instância de createcom builde desfazê-lo se o teste falhar?
mgold
Does #createler e devolver o objeto persistente do disco, ou ele devolver o objeto que está na memória depois persistência-lo? Em outras palavras, fazer é create(...)equivalente a create(...).reload?
Dennis
@mgold Vim é muito bom nesse tipo de coisa.
Expiação limitada de
15

O uso FactoryGirl.build(:factory_name)não persiste para o db e não chama save!, portanto, as validações do Active Record não serão executadas. Isso é muito mais rápido, mas as validações podem ser importantes.

O uso FactoryGirl.create(:factory_name)persistirá no banco de dados e chamará as validações do Active Record. Obviamente, isso é mais lento, mas pode detectar erros de validação (se você se importar com eles em seus testes).

abismo
fonte
11
Ou você poderia apenas fazer FactoryGirl.build (: factory_name) .valid? que executam validações sem salvar no banco de dados.
jinavar1
1

FactoryGirl.create()irá criar novos objetos e associações (se a fábrica tiver algum) para ele. Todos eles serão mantidos em um banco de dados. Além disso, ele acionará validações de modelo e banco de dados. Chamadas de retorno after(:build)e after(:create)serão chamadas depois que a fábrica for salva. Também before(:create)será chamado antes que a fábrica seja salva.

FactoryGirl.build()não salvará um objeto, mas ainda fará solicitações a um banco de dados se a fábrica tiver associações. Ele irá disparar validações apenas para objetos associados. Ligue de voltaafter(:build) será chamada depois que a fábrica for construída.

Observe que, na maioria dos casos, ao testar os modelos, é melhor usar build_stubbedpara melhor desempenho. Leia mais sobre isso aqui .

Nesha Zoric
fonte