如何在 rspec 中调用模块方法,并设置当前模块

How do I call a module method in rspec, with the current module set up

所以我有以下模块来处理推文的获取和保存。这一切都是在一个线程上完成的,我有兴趣在这个模块中测试两种方法:fetch_tweetssave_tweets

对于 fetch_tweets,我想验证是否调用了 save_tweets 方法。我不在乎它 returns.

对于 save_tweets,我想测试一条推文是否真的被保存了。

考虑到这一点,让我们看一些代码。

Twitter::TwitterHandler - 这生活在 lib/twitter/twitter_handler.rb

module Twitter
  module TwitterHandler

    def handle_tweets(twitter_client_object)
      Thread.new do
        begin
          twitter_lock(twitter_client_object)
        ensure
          ActiveRecord::Base.clear_active_connections!
        end
      end
    end

    def twitter_lock(twitter_client_object)
      TwitterTweet.with_advisory_lock('aisis-writer-tweets', 0) do
        fetch_tweets(twitter_client_object)
      end
    end

    def fetch_tweets(twitter_client_object)
      Rails.cache.fetch([:aisis_twitter_feed, Time.now.to_i/60/5], expires_in: 1.minute){
        twitter_client.user_timeline(user_id: '252157965', count: 100).map(&:as_json).select{ |h| h["text"].match(/aisiswriter/i) }.take(10).each do |tweet|
          save_tweets(tweet['id_str'], tweet['text'], tweet['created_at'])
        end
      }
    end

    def save_tweets(id, text, created_at)
      tweet = TwitterTweet.find_or_initialize_by(id: id)
      tweet.text = text
      tweet.created_at = created_at
      tweet.save
    end

  end
end

twitter_handler_spec.rb - 这住在 spec/twitter/twitter_handler_spec.rb

require 'rails_helper'
require_relative '../../lib/twitter/twitter_handler'

describe 'TwitterHandler' do

  context "fetch tweets method" do
    it "should fetch some tweets" do
      t = Time.parse("01/01/2010 10:00")
      Time.should_receive(:now).and_return(t)
      expect(fetch_tweets(twitter_client)).to receive(:save_tweets).with('342', 'Something', t).and_return nil
    end
  end
end

当我 运行 bin/rspec spec/twitter/twitter_handler_spec.rb 我得到:

Failures:

  1) TwitterHandler fetch tweets method should fetch some tweets
     Failure/Error: expect(fetch_tweets(twitter_client)).to receive(:save_tweets).with('342', 'Something', t).and_return nil
     NoMethodError:
       undefined method `fetch_tweets' for #<RSpec::ExampleGroups::TwitterHandler::FetchTweetsMethod:0x007ff1c724e300>
     # ./spec/twitter/twitter_handler_spec.rb:11:in `block (3 levels) in <top (required)>'

我该如何解决这个问题,以便我可以调用此方法以及此模块中的任何其他方法?

您不能调用模块的实例方法。您必须 includeextend 模块,然后调用包含或扩展模块的对象的方法。您从 rspec 得到的错误是因为您在示例中调用 fetch_tweets,但示例中未定义 fetch_tweets

一旦你解决了调用 fetch_tweets 的问题,那么你就必须处理这样一个事实,即你的 expect(fetch_tweets(...)) 期望是说 fetch_tweets 返回的对象正在运行接收 :save_tweets 的方法调用,这不是您想要的。根据您的描述,您希望设置一个期望,即包含或扩展 TwitterHandler 的任何对象都将收到 save_tweets 并且 然后 您想要调用 fetch_tweets

如果不清楚,我建议您阅读 Ruby 模块方法,然后阅读 RSpec。