【问题标题】:Django Unit Test Assert Database Transaction is ActiveDjango 单元测试断言数据库事务处于活动状态
【发布时间】:2015-01-15 08:41:21
【问题描述】:

我们正在编写一些单元测试来断言在函数内部的某些点有一个数据库事务处于活动状态。但是,我们正在努力如何准确地断言这一点,有谁知道我们该怎么做?浏览Django Transaction DocsSource Code for django.db.transaction 没有发现任何有用的信息。

这里有一些代码来说明我们正在努力实现的目标,使用Assertion Injection

def function_under_test():
    ... some stuff ....
    function_we_will_patch_to_assert_transaction_is_open()
    ... some more stuff ...

class MyTestCase(TestCase):

    def assert_transaction_is_active(self):
        self.assertTrue(...what goes in here to assert this?...)

    @patch('function_we_will_patch_to_assert_transaction_is_open'):
    def test_function_under_test__transaction_is_active(self, patched_fn):
        patched_fn.side_effect = self.assert_transaction_is_active

        function_under_test()

请注意:我们非常热衷于以与数据库无关的方式执行此操作(我们在 dev 中使用 sqlite,在其他地方使用 postgresql),但是如果有仅适用于 postgresql 的解决方案,那将是可行的。

【问题讨论】:

    标签: python django postgresql unit-testing transactions


    【解决方案1】:

    我们设法通过在测试类中添加以下函数来实现这一点。

    def assert_inside_atomic_block(self, using=None):
        """
        Returns a function that will assert we are inside an atomic transaction block. The purpose of this is to allow
        us to inject this assertion inside methods where we want to verify that a transaction is active.
    
        Does not work with django.db.TransactionTestCase because it automatically wraps each test in a transaction.
        """
    
        if issubclass(self.__class__, TransactionTestCase):
            raise AssertionError('Cannot determine if code is run inside a transaction with a TransactionTestCase')
    
        def _assert_inside_atomic_block(*args, **kwargs):
            if not get_connection(using=using).in_atomic_block:
                raise AssertionError('Not inside an atomic transaction block')
    
        return _assert_inside_atomic_block
    

    然后可以在测试中使用如下:

    @patch('function_we_will_patch_to_assert_transaction_is_open'):
    def test_function_under_test__transaction_is_active(self, patched_fn):
        patched_fn.side_effect = self.assert_inside_atomic_block()
    
        function_under_test()
    

    需要注意的重要一点:此技术不适用于基于 django.test.TransactionTestCase 的测试类 - 因为这将每个测试包装在事务中,断言永远不会失败。

    【讨论】:

      猜你喜欢
      • 2014-07-11
      • 2010-11-11
      • 1970-01-01
      • 1970-01-01
      • 2015-04-13
      • 2021-03-19
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      相关资源
      最近更新 更多