ruby rspec mock测试函数接收哈希

ruby rspec mock测试函数接收哈希,ruby,testing,rspec,tdd,rspec3,Ruby,Testing,Rspec,Tdd,Rspec3,我正在玩弄MailgunAPI,所有的功能现在似乎都可以工作了,我想用rspec模拟来测试它们 我在rspec/fixtures文件夹下制作了一些json装置,每个装置都有一个json,表示调用特定函数时的预期结果。我还做了一个小助手: module TestHelpers def self.get_json(filename:) JSON.parse File.read(filename) end end 我想测试的是这个函数: def self.get_messages_f

我正在玩弄MailgunAPI,所有的功能现在似乎都可以工作了,我想用rspec模拟来测试它们

我在rspec/fixtures文件夹下制作了一些json装置,每个装置都有一个json,表示调用特定函数时的预期结果。我还做了一个小助手:

module TestHelpers
  def self.get_json(filename:)
    JSON.parse File.read(filename)
  end
end
我想测试的是这个函数:

def self.get_messages_for(email:)
    sent_emails = []
    delivered_events = get_events_for(email: email)

    # :Accept => "message/rfc2822" will help us to get the raw MIME
    delivered_events.each do |event|
      response = RestClient::Request.execute method: :get ,
                                              url: event["storage"]["url"],
                                              user: "api", password:"#{configuration.api_key}",
                                              Accept: "message/rfc2822"
      sent_emails.push(JSON.parse(response))
    end
    sent_emails
  end
它使用此帮助器获取事件:

def self.get_events_for(email:, event_type: "delivered")
    delivered_to_target = []
    response = RestClient.get "https://api:#{configuration.api_key}"\
    "@api.mailgun.net/v3/#{configuration.api_domain}/events",
    :params => {
      :"event" => event_type
    }

    all_delivered = JSON.parse(response)["items"]

    all_delivered.each do |delivered|
      if (delivered.has_key?("recipients") and delivered["recipients"].include?(email)) or
        (delivered.has_key?("recipient") and delivered["recipient"].include?(email))
        delivered_to_target.push(delivered)
      end
    end
    delivered_to_target
  end
在我的规范中,我有:

it 'can get the list of previously sent emails to an email address' do

    allow(StudySoup).to receive(:get_events_for).with({email: email}) {
      Array(TestHelpers::get_json(filename: 'spec/fixtures/events.json'))
    }

    allow(RestClient::Request).to receive(:execute).with(any_args){
      TestHelpers::get_json(filename: 'spec/fixtures/messages.json')
    }

    expect(StudySoup.get_messages_for(email: email)["subject"]).not_to be nil
  end
但是,当我尝试运行rspec时,它总是有以下失败跟踪:

1) StudySoup can get the list of previously sent emails to an email address
     Failure/Error: url: event["storage"]["url"],

     TypeError:
       no implicit conversion of String into Integer
     # ./lib/StudySoup.rb:51:in `[]'
     # ./lib/StudySoup.rb:51:in `block in get_messages_for'
     # ./lib/StudySoup.rb:49:in `each'
     # ./lib/StudySoup.rb:49:in `get_messages_for'
     # ./spec/StudySoup_spec.rb:86:in `block (2 levels) in <top (required)>'
1)StudySoup可以获取以前发送到某个电子邮件地址的电子邮件列表
失败/错误:url:事件[“存储”][“url”],
类型错误:
没有将字符串隐式转换为整数
#/lib/StudySoup.rb:51:in`[]'
#/lib/StudySoup.rb:51:in'block in get_messages_for'
#/lib/StudySoup.rb:49:in'each'
#/lib/StudySoup.rb:49:in'get_messages_for'
#./spec/StudySoup_spec.rb:86:in `分块(2层)in'

我想我删除了
RestClient::Request.execute
方法,所以它应该可以工作,但没有。关于如何正确测试此函数,有什么想法吗?我试图像任何东西一样放置许多参数matcher(),hash_包括(:key=>value)。。。但是它仍然不起作用。

您确实已经删除了
execute
方法。这意味着rspec摆弄该类,以便尝试调用
execute
调用rspec提供的代码,而不是原始的inimplementation。特别是,该调用的所有参数的计算结果都是正常的

在您尝试更改参数匹配器时,会更改rspec是否确定方法调用与配置的存根之一匹配,但无法避免评估
event[“storage”][“url”]
会引发异常


当您为截取
get\u events\u时,您返回了一个数组数组,而不是散列数组:
array
调用
到a
的参数,这会将散列转换为键值对数组,而不是像我认为的那样将散列包装到数组中

在events.json文件中,我只有一个json散列,因此get_json的结果是一个散列(我已经在单独的rb脚本中对此进行了测试)。通常情况下,在生产中get_events_for将返回一个哈希数组,因此我认为应该将get_json强制转换为数组(我也尝试过删除强制转换,但它也不起作用),是否有任何方法可以将事件[“storage”][“url”]?比如event=double allow(event)。要接收(:[])…啊,问题是数组(foo)并不像你想的那样-它与[foo]不同,那么我如何构造一个只包含一个散列的数组呢?我做了一个快速的搜索,发现了唯一的东西,就像我说的
[foo]