RSpec mock method inside of select loop

本小妞迷上赌 提交于 2020-07-10 07:28:29

问题


I want to test simple class which iterate through array of hashes and return only those with status Pending which were updated more than 2 days ago.

  class FetchPending
    PROJECT_KEY = 'TPFJT'
    TWO_DAYS = Time.now - 2 * 24 * 60 * 60

    def call
      project.select do |issue|
        issue.fields.dig('status', 'name') == 'Pending' &&
          DateTime.parse(issue.fields.dig('updated')) < TWO_DAYS
      end
    end

    private

    def project
      @project ||= Jira::ProjectConnection.new(PROJECT_KEY).call
    end
  end

How to test fields method which is a method of Jira-Ruby gem. I think it comes from here (Field class in resource of gem) because nowhere else have I found fields method.

Here are my thoughts after debugging:

  • project.class - Array

  • issue.class - JIRA::Resource::Issue

my natural thinking was:

  before do
    # (...) some other mocks
    allow(JIRA::Resource::Issue).to receive(:fields)
  end

But I'm getting an error:

Failure/Error: allow(JIRA::Resource::Issue).to receive(:fields)

JIRA::Resource::Issue does not implement: fields

I have been struggling with this problem for DAYS, I'm pretty desperate here. How to mock this method?

Here is my rest of my specs:

RSpec.describe FetchPending do
  subject { described_class.new }

  let(:project_hash) do
    [
      {
        'key': 'TP-47',
        'fields': {
          'status': {
            'name': 'Pending'
          },
          'assignee': {
            'name': 'michael.kelso',
            'emailAddress': 'michael.kelso@example.com'
          },
          'updated': '2020-02-19T13:20:50.539+0100'
        }
      }
    ]
  end
  let(:project) { instance_double(Jira::ProjectConnection) }

  before do
    allow(Jira::ProjectConnection).to receive(:new).with(described_class::PROJECT_KEY).and_return(project)
    allow(project).to receive(:call).and_return(project_hash)
    allow(JIRA::Resource::Issue).to receive(:fields)
  end

  it 'return project hash' do
    expect(subject.call).include(key[:'TP-47'])
  end

回答1:


That's not the correct syntax to mock it to return project; and_return is for returning a value (such as a string or an integer), not an object; for an object, you must send it as a block. Additionally, if call is a valid method on a Jira::ProjectConnection object that returns the value of project_hash, you can directly mock its behavior when declaring your instance double (this functionality is unclear from the Relish docs bc they are kinda terrible). Something like this will probably work:

let(:project) { instance_double(Jira::ProjectConnection, call: project_hash) }

before do
  # Ensure new proj conns always return mocked 'project' obj
  allow(Jira::ProjectConnection).to receive(:new).with(
    described_class::PROJECT_KEY
  ) { project }
end

If it still doesn't work, try temporarily replacing described_class::PROJECT_KEY with anything to debug; this can help you confirm if you specified the wrong arg(s) being sent to new.

With regard to the error message, it looks like JIRA::Resource::Issue doesn't have a fields attribute/method, though fields appears to be nested in attrs? The JIRA::Resource::Project#issues method also translates the issues in the JSON into Issue objects, so if you're using that method you will need to change the contents of project_hash.



来源:https://stackoverflow.com/questions/60365533/rspec-mock-method-inside-of-select-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!