views:

969

answers:

1

I am using Mocha and Factory_girl in a JRuby rails application. When I call the factory I would like to return the objects with some mocking already done. Here is a code snippet of what I am trying to do.

Factory.define :tweet_feed_with_tweets, :parent => :tweet_feed do |t|
  t.expects(:pull_tweets).returns([Factory.build(:status),Factory.build(:status)])
end

Because I do not want my unit and functional test to actually pull from the twitter API i want to stub the method so it returns what I want. But, this is not working. The object comes back without any stubbing done. Is there a way to actually have stubbing performed on an object created with factory girl before it gets returned to you?

+1  A: 

Looking at the documentation & source code for factory_girl, it looks like the object yielded to the block (t, in your example) is an instance of a Factory and not an instance of the object you want to construct (the tweet_feed_with_tweets, in your example). This means that setting an expectation for the pull_tweets method on t is setting the expectation on the Factory instance and not on the object that will be constructed when you call Factory(:tweet_feed_with_tweets). I think this explains why your example is not working as you expect.

I may be wrong, but I can't see a way of adding the expectation within the Factory.define block. You've probably already thought of this, but I think you'd be better off adding the expectation in the test after you've constructed the instance :-

def test_should_do_something
  tweet_feed = Factory(:tweet_feed)
  tweet_feed.expects(:pull_tweets).returns([Factory.build(:status), Factory.build(:status)])
  # test stuff here
end

If you need this in multiple places, you can extract it into a method :-

def test_should_do_something
  tweet_feed = build_tweet_feed_with_tweets
  # test stuff here
end

private

def build_tweet_feed_with_tweets
  tweet_feed = Factory(:tweet_feed)
  tweet_feed.expects(:pull_tweets).returns([Factory.build(:status), Factory.build(:status)])
  return tweet_feed
end

A couple of other thoughts :-

  1. I think setting expectations in such a hidden away place is probably a bad idea anyway.
  2. If you are going to do it, I would have thought using stubs was more appropriate than expects.
  3. It might be worth separating the pull_tweets method (and any similar methods) into a TwitterAPI class. That way it wouldn't seem so bad that you need to set up an expectation on the TwitterAPI in the test.

I hope some of that helps.

floehopper