Question: Rails 5 - Errors with FactoryGirl

Question

Rails 5 - Errors with FactoryGirl

Answers 1
Added at 2016-12-23 21:12
Tags
Question

I'm with the following problem.

I'm using Factory Girl Rails with variables like this:

FactoryGirl.define do
  conta_destino_matriz = FactoryGirl.create(:conta_pessoa_fisica, saldo: 0)
  conta_origem_filial = FactoryGirl.create(:conta_pessoa_fisica, saldo: 1000, ancestry: conta_destino_matriz.id)

  codigo_transacional =  TransacaoHelper::Gerador.codigo_alphanumerico(
    tipo: 'transferencia', conta_origem_id: conta_origem_filial.id, conta_destino_id: conta_destino_matriz.id
  )

  factory :transacao_transferencia_matriz, class: Transacao do
    tipo { 'transferencia' }
    valor { '250' }
    conta_origem_id { conta_origem_filial.id }
    conta_destino_id { conta_destino_matriz.id }

    trait :campos_completos do
      codigo_transacional { codigo_transacional }
      conta_origem_valor_antes_transacao { conta_origem_filial.saldo }
      conta_destino_valor_antes_transacao { conta_destino_matriz.saldo }
      estornado { false }
      codigo_transacional_estornado { nil }
    end
  end
end

Where conta_destino_matriz is declared outside the factory name definition. This is need because two attributes from de factory need to have two values from some association like:

conta_destino_id                    { conta_destino_matriz.id }
conta_destino_valor_antes_transacao { conta_destino_matriz.saldo }

And another test uses a factory with the same association factory conta_pessoa_fisica:

FactoryGirl.define do
  conta_origem_hierarquia_igual = FactoryGirl.create(:conta_pessoa_fisica, saldo: 1000)
  conta_destino_hierarquia_igual = FactoryGirl.create(:conta_pessoa_fisica, saldo: 0, ancestry: conta_origem_hierarquia_igual.id)
  codigo_transacional_hierarquia_igual =  TransacaoHelper::Gerador.codigo_alphanumerico(
      tipo: 'transferencia', conta_origem_id: conta_origem_hierarquia_igual.id, conta_destino_id: conta_destino_hierarquia_igual.id
  )

  conta_origem_hierarquia_diferente = FactoryGirl.create(:conta_pessoa_fisica, saldo: 1000)
  conta_destino_hierarquia_diferente = FactoryGirl.create(:conta_pessoa_fisica, saldo: 0)

  factory :transacao_transferencia_hierarquia, class: Transacao do
    tipo { 'transferencia' }
    valor { '250' }
    conta_origem_id { conta_origem_hierarquia_igual.id }
    conta_destino_id { conta_destino_hierarquia_igual.id }

    trait :campos_completos do
      codigo_transacional { codigo_transacional_hierarquia_igual }
      conta_origem_valor_antes_transacao { conta_origem_hierarquia_igual.saldo }
      conta_destino_valor_antes_transacao { conta_destino_hierarquia_igual.saldo }
      estornado { false }
      codigo_transacional_estornado { nil }
    end

    trait :diferente do
      conta_origem_id { conta_origem_hierarquia_diferente.id }
      conta_destino_id { conta_destino_hierarquia_diferente.id }
    end
  end
end

And this is the association:

FactoryGirl.define do
  factory :pessoa_fisica do
    cpf { Faker::Number.number(11) }
    nome { Faker::Name.name }
    data_nascimento { Date.today.strftime('%Y-%m-%d') }

    factory :pessoa_fisica_invalida do
      id { 0 }
      cpf { Faker::Number.number(10) }
      nome { '' }
      data_nascimento { (DateTime.now + 1.day).strftime('%Y-%m-%d') }
    end
  end
end

The error that I got happens in the 'nome' attribute from the :pessoa_fisica class was already stored. The field mus be unique and only characters.

nome { Faker::Name.name }

So, when my test run and It calls :transacao_transferencia_matriz and :transacao_transferencia_hierarquia and sometimes I got an error that says

`raise_validation_error': A validation failed: Nome is already taken (ActiveRecord::RecordInvalid)

And the worse, it is that I got this errors not always, but sometimes.

Answers
nr: #1 dodano: 2016-12-23 21:12

The following in your factory does not guarantee uniqueness:

nome { Faker::Name.name }

Faker generates the name from a limited set and will sometimes return a name that already exists in your database. As you have a validation check for the model it is of course failing.

To guarantee uniqueness use sequence in the name, within your factory:

sequence(:nome) {|n| "#{Faker::Name.name} #{n}" }

You should ideally also be ensuring that your database is in a clean state for each test - check out the database cleaner gem

Source Show
◀ Wstecz