python - 使用模拟对象的困境

标签 python unit-testing mocking

假设我想断言 result 是特定格式,我可能会将返回值设置为 (True, 'Success')

def batch_move(self, *args, **kwargs):
  ''' 
  Move a batch of files to its respective destinations.
  Return type: tuple (boolean, message)
                      T/F    , 'string' / str(exception)
  '''

  srcs= kwargs.get('srcs', None)
  dests = kwargs.get('dests', None)

  try:
    if srcs and dests:
       # map srcs and dests into dictionary (srcs --> keys, dests --> values)
       src_dest= dict(zip(srcs, dests))     

       for src, dest in src_dest:
         if os.path.exists(src):
           if os.path.exists(dest):
              shutil.rmtree(dest)
           shutil.move(src, dest)   # either way we will proceed to move
         else:
           return (False, '%s does not exist!' % src)
       return (True, 'Success!')

    else:
       return (False, 'Something gone wrong with those kwargs...')
  except Exception as e:
    return (False, e)

为了得到 return (True, 'Success!')

  1. 修补 os.path.exists 并将 True 作为返回值。但是在一个单元测试中我想跳过这个,我该如何修补 os.path.exists
    if os.path.exists(dest):  # I want to skip this
         shutil.rmtree(dest)
  1. 如何修补 shutil.move(src, dest)?我是否只提供 True 这样它就不会产生错误?如果我想要它失败并捕获异常怎么办?我该如何模拟呢? (我并不总是知道要捕获哪个异常,这是使用 Exception as e 的主要原因)。

  2. 如果我真的传递了这个函数,是否真的意味着没有捕获到异常并且它遍历了每一行?还是因为我设置了 `mock_object.return_value = (True, 'Success!')?

  3. 我只使用了两个依赖项,我是否需要将所有外部依赖项(例如(os、sys、math、datetime))全部打补丁?或者如果我的函数正在使用其他函数(已重构)

 def f1(*args, **kwargs):
    f2(..)   # use math, plot, datetime
    f3(..)   # use math and datetime
    f4(..)   # use datetime

    ....

谢谢。很抱歉问题很长。我真的很想擅长编写单元测试。

最佳答案

我必须说,在这个特定的用例中,我认为修补/模拟不是最好的选择......

对于这个单元测试,我将在文件系统中创建一个结构,在磁盘中的该结构上运行算法并检查不同的结果(所有这些都没有模拟操作系统或 shutil)。

通常我倾向于在外部设置困难或缓慢(即:可能必须设置一些外部数据库)或者当它会停止测试(即:打开一些对话框)或者我想做的时候使用补丁一些难以通过其他方式检查的内容(例如计算是否实际访问了某些缓存)。

除此之外,太多的补丁/模拟给我的印象是你的设计有问题(这不是在考虑单元测试的情况下完成的),因此,将它分解成更小的 block 进行测试可能会有所帮助。 ..

关于python - 使用模拟对象的困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10288918/

相关文章:

c# - 如何在 C# 中模拟基类属性或方法

python - 使用辅助列名列表访问 Django 查询集的值

python - 创建将在指定 python 虚拟环境中运行的 .py 文件,同时还通过指定路径导入其他文件

javascript - 找不到变量 : Promise in Phantomjs

iOS UI 测试与集成测试

.net - 在 Moq 回调中使用当前对象实例

python - 如何在使用 range() 函数从列表中删除项目时迭代列表?

python - 大文本文件的并行计算

Python: self.assertEqual(a, b, msg) --> 我想要 diff AND msg

go - 通过担架/验证模拟,不同的返回参数