所以我有以下模块来处理推文的获取和保存。这都是在一个线程上完成的,我有兴趣在这个模块中测试两种方法:
fetch_tweets
和save_tweets
对于
fetch_tweets
,我想验证是否调用了 save_tweets
方法。我不在乎它返回什么。
对于
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)>'
如何修复此问题,以便我可以调用此方法以及此模块中的任何其他方法?
您无法调用模块的实例方法。您必须
include
或 extend
模块,然后调用包含或扩展该模块的对象上的方法。您从 rspec 得到的错误是因为您从示例中调用 fetch_tweets
,但示例中未定义 fetch_tweets
。
一旦解决了调用
fetch_tweets
的问题,那么您就必须处理以下事实:您 expect(fetch_tweets(...))
的期望是 fetch_tweets
返回的对象将接收 :save_tweets
的方法调用,这不是你想要的。根据您的描述,您希望设置一个期望,即无论包含或扩展 TwitterHandler
的对象都将收到 save_tweets
以及您想要调用 fetch_tweets
的 then。
如果不清楚,我建议您阅读 Ruby 模块方法,然后阅读 RSpec。
如果模块方法定义为
self.method_name
,则可以调用它们。
请参阅以下示例:https://mixandgo.com/learn/ruby/module-testing-with-rspec
require 'spec_helper'
module MyMath
def self.number
5
end
end
RSpec.describe MyMath do
it 'returns five' do
expect(MyMath.number).to eq(5)
end
end
如果该模块与测试不在同一个文件中,您可以需要它。 如果模块像您的示例中那样嵌套,您必须将 handle_tweets 的定义更改为
def self.handle_tweets
,然后在测试中使用 Twitter::TwitterHandler.method_name
调用它。