简体   繁体   中英

Rspec how to test in inject method

I have a method that looks like this:

  def self.average_top_level_comments_leaders
    top_level_comment_count = CrucibleComment.group(:user_id).where(parent_comment_id: nil).order('count_all DESC').count
    code_review_assigned_count = Reviewer.group(:user_id).order('count_all DESC').count

    division_result = top_level_comment_count.inject({}) do |result, item|
      id = item.first #id =12
      count = item.last #value = 57
      if (count && code_review_assigned_count[id]) 
        result[id] = (count/ code_review_assigned_count[id]).round(2) 
        #result[12] = 57/12 = 3.3, => {12, 3.3}
      end
      result 
    end
  end

This method returns a hash with the IDs as keys and the results of the division as the values.

I have successfully tested top_level_comment_count and code_review_assigned count, but I am having trouble figuring out how I can test the 4 other things that are in the do block:

.first, .last, .round(2), result

I am trying to test .first and this is what I have so far:

describe '#average_top_level_comments_leaders' do
    subject { User.average_top_level_comments_leaders}

    let(:avg_top_level_comments) { double }
    let(:code_review_count) { double }
    let(:item) { double( {id: 12}) }

    context 'when getting the comment count succeeds ' do
      before do
        allow(CrucibleComment).to receive(:group).with(:user_id).and_return(avg_top_level_comments)
        allow(avg_top_level_comments).to receive(:where).with(parent_comment_id: nil).and_return(avg_top_level_comments)
        allow(avg_top_level_comments).to receive(:order).with('count_all DESC').and_return(avg_top_level_comments)
        allow(avg_top_level_comments).to receive(:count).and_return(avg_top_level_comments)

        allow(avg_top_level_comments).to receive(:inject).and_return(avg_top_level_comments)
        allow(item).to receive(:first).and_return(item)

        allow(Reviewer).to receive(:group).with(:user_id).and_return(code_review_count)
        allow(code_review_count).to receive(:order).with('count_all DESC').and_return(code_review_count)
        allow(code_review_count).to receive(:count).and_return(code_review_count)
        allow(code_review_count).to receive(:round).with(2).and_return(code_review_count)
      end

      it 'and the correct parameters are called' do
        expect(CrucibleComment).to receive(:group).with(:user_id)
        subject
      end

      it 'and comment count is calling descending correctly' do
        expect(avg_top_level_comments).to receive(:order).with('count_all DESC')
        subject
      end

      it 'item gets the first result' do
        expect(item).to receive(:first)
        subject
      end
    end
  end

I cannot get the last it statement to pass. I am trying to expect(item).to receive(:first), but it says this in the error:

Failure/Error: expect(item).to receive(:first) (Double).first(*(any args)) expected: 1 time with any arguments received: 0 times with any arguments

Any idea why this is not passing? The other two its are passing

The item double is never used in the test, so when it reaches:

expect(item).to receive(:first)

it fails.

If you were expecting the item double to be used within the inject block here:

division_result = top_level_comment_count.inject({}) do |result, item|

merely by virtue of it having the same name, it doesn't work that way. You'd need to define a method on the avg_top_level_comments double that returns the item double when inject is called.

But, you shouldn't do that. Throw all of this out and use real model instances for the test. It will be much easier to read and maintain.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM