【问题标题】:Mocking a function called in django form模拟以 django 形式调用的函数
【发布时间】:2013-08-29 10:55:09
【问题描述】:

我有两个模块。

a.py

def get_resource(arg1, arg2):
   return Modelobject based on arg1 and arg2 or None

b.py(形式)

from a import get_resource
class A(forms.Form):
 arg1 = forms.CharField()
 arg2 = forms.CharField()
 def clean(self):
   res = get_resource(arg1, arg2)
   if res is None:
    validationerror
   else:
    cleaned_data.update(res_key=res)

现在我需要模拟 get_resource 部分,这样我就不需要任何数据库,但我无法让它工作。

这是我尝试过的,但它不起作用。我做错了什么?

class Test(TestCase):
  def test_form_a(self):
    with patch('b.get_resource') as mock_tool:
      mock_tool.return_value = MagicMock(spec=MusicModel)
      form_data = {'arg1': '1', 'arg2': 'Music'}
      form = A(data=form_data)

我还用函数尝试了 side_effects

def my_side_effect(*args, **kwargs):
  return value based on arg[0] and arg[1]

mock_tool.side_effect = my_side_effect

由于我在模拟和测试方面相当新手,谁能告诉我正确的方向吗?

【问题讨论】:

  • 为什么,特别是,您要模拟它以便不需要数据库?我意识到在“纯”单元测试中会出现这种情况,但是 Django 的单元测试环境包括设置一个测试数据库,这样您就不必担心这类事情。
  • 好吧,我刚刚开始测试和其他东西。而且由于我只想检查表单的 clean 方法的覆盖,我想看看是否可以在不接触数据库的情况下完成它。我想如果我接触数据库并创建固定装置,那么所有这些都不会是单元测试。

标签: python django unit-testing mocking


【解决方案1】:

我不熟悉 django 表单,所以基本上我以适当的可测试方式修改了您的脚本。似乎测试都通过了,也许您在问题中省略了一些原因代码?但是,以下是供您参考的工作示例。

% 鼻子测试 test.py test_no_patch_a (test.Test) ...好的 test_patch_a (test.Test) ...好的

a.py

def get_resource(arg1, arg2):
 return arg1

b.py

from a import get_resource
class A(object):
 arg1 = 'arg1'
 arg2 = 'arg2'
 res = None
 def __init__(self, data):
   self.res = get_resource(data['arg1'], data['arg2'])

 def bow(self):
   if self.res is None:
    return 'validationerror'
   else:
    return self.res

test.py

import unittest
from mock import patch
from b import A

class Test(unittest.TestCase):
  def test_patch_a(self):
    with patch('b.get_resource') as mock_tool:
      mock_tool.return_value = 'patched'
      data = {'arg1': '1', 'arg2': 'Music'}
      form = A(data=data)
      self.assertEqual('patched', form.bow())

  def test_no_patch_a(self):
    data = {'arg1': '1', 'arg2': 'Music'}
    form = A(data=data)
    self.assertEqual('1', form.bow())

【讨论】:

    【解决方案2】:

    更新:我想我发现了问题所在。虽然我很难理解为什么会发生这种情况,但这一切都取决于进口。显然,我需要在补丁中导入表单类并在实例化表单后定义返回值:

    class Test(TestCase):
      def test_form_a(self):
        with patch('b.get_resource') as mock_tool:
          from b import A
          form_data = {'arg1': '1', 'arg2': 'Music'}
          form = A(data=form_data)
          mock_tool.return_value = MagicMock(spec=MusicModel)
    

    我猜这都是模块加载造成的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-23
      • 1970-01-01
      • 2021-06-03
      • 2020-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-31
      相关资源
      最近更新 更多