Возвращение макетов от фабричной девушки

Я использую Mocha и Factory_girl в приложении JRuby rails. Когда я звоню на фабрику, я хочу вернуть объекты с уже сделанным издевательством. Вот фрагмент кода того, что я пытаюсь сделать.

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

Поскольку я не хочу, чтобы мой модульный и функциональный тест действительно извлекался из API твиттера, я хочу заглушить метод, чтобы он возвращал то, что я хочу. Но это не работает. Объект возвращается без каких-либо заглушек. Есть ли способ на самом деле выполнить заглушку для объекта, созданного с помощью factory girl, прежде чем он будет возвращен вам?

Ответов (2)

Решение

Глядя на документацию и исходный код 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. Если вы собираетесь это сделать, я бы подумал, что использование stubsбыло бы более подходящим, чем expects.
  3. Возможно, стоит разделить pull_tweetsметод (и любые подобные методы) на TwitterAPIкласс. Таким образом, это не выглядело бы так плохо, что вам нужно настроить ожидание TwitterAPIв тесте.

Надеюсь, что-то из этого поможет.

Теперь доступны обратные вызовы:

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