ruby-on-railstestingfactoryfactory-botaasm

How do you override :set_initial_state from AASM when testing with Factory Girl factories?


Update

Answered below. In case the linked site disappears, you can use mocha to stub the initial state and prevent overwriting as in ...

require 'mocha'
class OrderTest < ActiveSupport::TestCase
  def setup
    Order.any_instance.stubs(:set_initial_state)
    @order = Factory(:order, :state => "other_state")
  end

  ...
end

Original Question

I am currently running the Acts As State Machine Rails Plugin (has been a huge time saver, incidentally) and having some challenges using it with Factory Girl (also wonderful).

I want to be able to set the object state when I create the object with Factories. A generalized way of asking this question is "how do you call class methods when creating a object with Factories?"

class Transporter < ActiveRecord::Base
  validates_presence_of :company_name, :on => :update
  acts_as_state_machine :initial => :created, :column => 'status'
  state :created
  state :active
  state :inactive, :after => :inactivate_transporter_activity
end

Factory.define :transporter do |f|
  f.sequence(:company_name) {|n| "transporter_company#{n}"}
end

>> t=Factory(:transporter)
=> <Transporter ... status: "created">
>> t=Factory(:transporter, :status => 'active')
=> <Transporter ... status: "created"> #as expected, changes state back
>> t.activate!
=> true
>> t
=> <Transporter ... status: "active">

I can always call the t.activate! method within every test, but this will make my tests brittle. I'm looking for a way to run this method at Factory creation level or set it within factory.rb.

Thanks...


Solution

  • You can use a mocking framework (mocha) to override set_initial_state and get the correct state on your object.

    >> require 'mocha'
    => []
    >> Transporter.any_instance.stubs(:set_initial_state)
    => #<Mocha::Expectation:0x21ee6e4 ...
    >> t = Factory(:transporter, :state => "active")
    => #<Transporter ... state: "active">
    

    Idea stolen from here.