在循环内进行Rspec测试

时间:2016-07-10 11:09:34

标签: ruby-on-rails ruby unit-testing rspec

我正在尝试在循环中测试代码,我将如何解决这个问题:

class MyClass
  def initialize(topics, env, config, limit)
    @client = Twitter::Streaming::Client.new(config)
    @topics = topics
    @env = env
    @limit = limit
  end

 def start
   @client.filter(track: @topics.join(",")) do |object|
   # how would I test the code inside here, basically logical stuff
    next if !object.is_a?(Twitter::Tweet)

    txt = get_txt(object.text)
  end
end

有办法做到这一点吗?

3 个答案:

答案 0 :(得分:0)

如果您认为可以使用具有方法double的{​​{1}} Twitter::Streaming::Client,并且在调用此方法时会返回所需的输出:

filter

您需要手动构建let(:client) { double 'Twitter Client', filter: twitters } 对象(抱歉由于我缺乏上下文,但我从未使用过Twitter客户端),然后您可以对twitters方法的结果进行断言。

答案 1 :(得分:0)

正如您所看到的,测试该代码非常棘手。这是因为依赖于Twitter客户端gem。

你可以走几条路:

  1. 不要测试它 - Twitter客户端gem应该为您提供Twitter::Tweet个对象。您只测试您的逻辑,即get_txt方法

  2. 做@Marcus Gomes所说的 - 创建一个实现filter方法的集合双。

  3. 我更愿意做的是在规范中隐藏@client.filter来电。

  4. 例如,在您的规范中:

    some_collection_of_tweets = [
      double(Twitter::Tweet, text: "I'll be back!"),
      double(Twitter::Tweet, text: "I dare ya, I double dare ya!")
    ]
    @my_class = MyClass.new(topics, env, config, limit)
    allow(@my_class.client).to receive(:filter).and_return(some_collection_of_tweets)
    

    这意味着每次课程调用some_collection_of_tweets时都会返回@client.filter集合,并且通过让您构建数据,您可以设置预期。

    您需要更改的一件事是在课堂上设置attr_reader :client。此类测试的唯一副作用是您将代码绑定到Twitter客户端的界面。

    但就像其他一切......权衡:)

    希望有所帮助!

答案 2 :(得分:0)

如果您真的想测试无限循环逻辑,也许你可以做这样的事情?

RSpec.describe MyClass do
  subject { MyClass.new(['foo','bar'], 'test', 'config', 1) }

  let(:streaming_client) { Twitter::Streaming::Client.new }

  describe '#start' do
    let(:valid_tweet) { Twitter::Tweet.new(id: 1) }

    before do
      allow(Twitter::Streaming::Client).to receive(:new)
        .with('config').and_return(streaming_client)
    end

    after { subject.start }

    it '#get_txt receives valid tweets only' do
      allow(valid_tweet).to receive(:text)
        .and_return('Valid Tweet')

      allow(streaming_client).to receive(:filter)
        .with(track: 'foo,bar')
        .and_yield(valid_tweet)

      expect(subject).to receive(:get_txt)
        .with('Valid Tweet')
    end

    it '#get_txt does not receive invalid tweets' do
      allow(streaming_client).to receive(:filter)
        .with(track: 'foo,bar')
        .and_yield('Invalid Tweet')

      expect(subject).not_to receive(:get_txt)
    end
  end
end