2016-07-23 53 views
1

我正在用mailgun API進行遊戲,所有的功能似乎都能正常工作,我想用rspec mocks來測試它們。ruby​​ rspec mocks測試函數接收哈希

我在rspec/fixtures文件夾下創建了一些json fixture,當我調用一個特定的函數時,每個文件夾都有一個表示預期結果的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)>' 

我以爲我掐滅了RestClient::Request.execute方法,因此它應該工作,但事實並非如此。關於如何正確測試此功能的任何想法?我試圖把許多參數匹配成任何東西(),hash_including(:key => value)......但它仍然不起作用。

回答

1

你的確已經剔除了execute方法。這意味着rspec與該類一起撥動,以致嘗試呼叫execute調用rspec提供的代碼而不是原始實現。特別是,該調用的所有參數都按正常方式評估。

更改參數匹配器,因爲您已嘗試更改rspec是否決定方法調用匹配其中一個配置的存根,但無法避免評估event["storage"]["url"]引發異常這一事實。

當你存根get_events_for你返回數組,而不是散列數組的數組:Array呼籲其論據是把你的散列成鍵值對的數組,而不是包裝散在數組to_aryto_a因爲我認爲你認爲它確實如此。

+0

在events.json文件中,我只有一個json哈希,所以我的get_json的結果是哈希(我已經在單獨的rb腳本中測試過了)。通常在生產中get_events_for將返回一個哈希數組,因此我認爲我應該將get_json轉換爲數組(我也嘗試刪除該轉換,但它也不起作用) – YaphatS

+0

有什麼方法可以將事件[「storage」 ] [ 「網址」]? (事件).to接收(:[])... – YaphatS

+0

啊,所以問題是Array(foo)不會做你認爲的事情 - 它和[foo]不一樣 –