从工厂女孩返回模拟对象

时间:2009-02-25 23:50:01

标签: ruby unit-testing mocking factory-bot mocha

我在JRuby rails应用程序中使用Mocha和Factory_girl。当我打电话给工厂时,我想通过已经完成的一些模拟来返回对象。这是我想要做的代码片段。

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

因为我不希望我的单元和功能测试实际上从twitter API中拉出来我想要存根方法所以它返回我想要的东西。但是,这不起作用。该对象返回时没有任何存根。有没有办法在返回给你的工厂女孩​​创建的对象上实际执行存根?

2 个答案:

答案 0 :(得分:6)

现在可以使用回调:

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

答案 1 :(得分:1)

查看文档& factory_girl的源代码,看起来像块(t,在您的示例中)产生的对象是Factory的实例,而不是您要构造的对象的实例(在您的示例中为tweet_feed_with_tweets)。这意味着在pull_tweets上设置t方法的期望是在Factory实例上设置期望值,而不是在调用Factory(:tweet_feed_with_tweets)时将构造的对象上设置期望值。我认为这解释了为什么你的例子没有像你期望的那样工作。

我可能错了,但我看不到在Factory.define区块中添加期望的方法。您可能已经考虑过这一点,但我认为您在构建实例后在测试中添加期望会更好: -

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

如果您需要在多个地方使用它,可以将其提取到方法中: -

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

其他一些想法: -

  1. 无论如何,我认为在这样一个隐藏的地方设定期望可能是一个坏主意。
  2. 如果你打算这样做,我会认为使用stubsexpects更合适。
  3. pull_tweets方法(和任何类似的方法)分成TwitterAPI类可能是值得的。这样,你需要在测试中TwitterAPI设置一个期望,这似乎不是那么糟糕。
  4. 我希望其中一些有帮助。