2014-10-17 78 views
0

我正在爲一個函數編寫一個單元測試,該函數將確認使用正確的參數調用其中調用的函數。問題是其中一個參數是一個生成器。比較mock.assert_has_calls中的生成器對象

有沒有辦法比較使用assert_has_calls調用fn的生成器的內容? 「AssertSequenceEqual」中展示了我正在尋找的行爲示例。實際上,test_use_fn因爲它正在比較的生成器對象不同而失敗。

import mock 

def fn(entries): 
    pass 

def use_fn(entries, convert=lambda x: x): 
    entries = (convert(entry) for entry in entries) 
    entries = fn(entries) 
    entries = fn(entries) 

@mock.patch('fn') 
def test_use_fn(self, mock_fn): 
    mock_fn.return_value = 'baz' 
    entries = ['foo', 'bar'] 
    use_fn(entries) 
    call_1 = mock.call((entry for entry in entries)) 
    call_2 = mock.call('baz') 
    mock_fn.assert_has_calls([call_1, call_2]) 
+0

沒有兩個生成器對象是相同的,所以它們總是會失敗一個相等或「is」測試。嵌套的內部函數也是如此。 – aruisdante 2014-10-17 18:35:48

+2

這看起來像是http://XYproblem.info的例子。你能否進一步解釋爲什麼你想驗證這樣的電話? – 2014-10-17 19:12:54

+0

@aruisdante,我知道;這是問題的核心。我正在尋找的行爲示例展示在'assertSequenceEqual'中。 – nodocitna 2014-10-17 20:13:20

回答

2

您可以使用call_args_listhttps://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.call_args_list

我認爲你會檢查發電機的每一個項目都是相同的。我寫了一個測試用例類的assertEqualGenerators()方法來完成這項工作(如果參數不是生成器,使用標準assertEqual())。模塊文件名是mock_generators.py,您必須使用mock_generators.fn來修補fn。最後一個技巧是call對象參數:請看https://docs.python.org/3/library/unittest.mock.html#unittest.mock.call.call_list瞭解如何獲取數據的細節(在您的情況下,第一個元素是您需要的)。

import unittest 
from unittest import mock 

def fn(entries): 
    pass 

def use_fn(entries, convert=lambda x: x): 
    entries = (convert(entry) for entry in entries) 
    entries = fn(entries) 
    entries = fn(entries) 

class MyTestCase(unittest.TestCase): 

    def assertEqualGenerators(self,a,b): 
     try: 
      for x,y in zip(a,b): 
       self.assertEqual(x, y) 
     except TypeError: 
      self.assertEqual(a, b) 

    @mock.patch("mock_generators.fn") 
    def test_use_fn(self, mock_fn): 
     mock_fn.return_value = 'baz' 
     entries = ['foo', 'bar'] 
     use_fn(entries) 
     calls = [mock.call((entry for entry in entries)), 
        mock.call('baz')] 
     self.assertEqual(len(calls), mock_fn.call_count) 
     for a,b in zip(mock_fn.call_args_list,calls): 
      self.assertEqualGenerators(a[0],b[0]) 


if __name__ == '__main__': 
    unittest.main() 
+0

感謝您指點我call_args_list的方向。 – nodocitna 2014-10-20 16:05:43