Fixtures without validation with Factory Girl

Factory Girl is my fixture replacement library of choice. It improves tests readability and maintainability. It’s also customizable.

There are sometimes situations when you want to create test scenarios that checks how your app is handling invalid data (not user input, but invalid records that already sit in your database). To do this you first need to put this invalid data to your db.

You could accomplish this with such line:

@user = Factory(:user, :email => "not a correct email address")

However, factory girl would raise an exception here, because that’s the default strategy of creating new fixtures – raise exception if save fails (because of validation errors for example).

Thankfully we can use our own strategy of creating new fixtures, such that does save records without validation.

First let’s define our new strategy:

class Factory::Proxy::CreateWithoutValidation < Factory::Proxy::Build
  def result
    @instance.save(false)
    @instance
  end
end
 
class Factory
  def self.create_without_validation (name, overrides = {})
    factory_by_name(name).run(Proxy::CreateWithoutValidation, overrides)
  end
end

Now we can use it while defining new factory:

Factory.define :invalid_user, :class => User, :default_strategy => :create_without_validation do |f|
  ...
end

And then we can happily create invalid fixtures without any exceptions raised.

  • http://www.fatfreecrm.com Michael Dvorkin

    Nice tip, thanks!!

  • http://blog.tuxicity.se Johan

    Hey!

    Nice tip! But in what file do you put the strategy?

    • Michał Szajbe

      I usually keep strategies and factories in the same file.
      In larger projects I use different approach – each model has it’s own file with factories. I may write about it soon.

  • http://blog.tuxicity.se Johan

    I have as you say, one factory file for each model. That seems to be the default for Factory Girl. That’s why I was wondering where to put the strategy, so that it would be shared between all factories.

  • http://twitter.com/chrisbelpaire Christophe Belpaire

    This is nice bute not working with recent version of rails/factory_girl
    Version working with rail 3.1.3 and factory_girl 2.3.2 :

    class FactoryGirl::Proxy::CreateWithoutValidation false)
    @instance
    end
    end

    module FactoryGirl
    def self.create_without_validation (name, overrides = {})
    factory_by_name(name).run(FactoryGirl::Proxy::CreateWithoutValidation, overrides)
    end
    end