如何在 Django 测试中强制事务中的竞争条件?

bia*_*pio 7 python testing django transactions race-condition

有没有办法使用多线程运行 django 测试并强制竞争条件?我想确保处理事务错误的代码路径被执行。更具体地说,我希望能够产生 2 个线程,这些线程将尝试对数据库执行相同的操作,其中一个成功,另一个失败。我正在使用 django 中的测试框架。

Python伪代码:

def some_method():
  try
    with transaction.atomic():
      objectA = get_object_from_db()
      objectA.delete()
  except Error:
    # error handling code to be run


class TestClass(TransactionalTestCase):
  def test_some_method():
    # run two threads and make sure that the race condition was present and some_method recovered successfully
Run Code Online (Sandbox Code Playgroud)

jac*_*ier 2

从我读到的内容来看,您想要涵盖处理异常的路径。我问你这个问题:你真的需要在多线程竞争条件的情况下触发它,还是只是想确保在发生这种情况时它会做正确的事情?

这就是我要做的:

import unittest
import mock


# added just mimic django's orm for the purpose of the demo
class QuerySet(object):
  def delete(self):
    pass

def get_object_from_db():
  return QuerySet()

def some_method():
  try:
    objectA = get_object_from_db()
    objectA.delete()
    return True # this should be whatever you want to do in case it worked
  except Exception: # I would look up and check what ever error the django orm is raising.
    return False # this should be whatever you want to do in case it didn't work

class TestClass(unittest.TestCase):
  def test_some_method_in_case_it_worked(self):
    self.assertEqual(some_method(), True)

  def test_some_method_in_case_it_did_not_work(self):
    with mock.patch('__main__.get_object_from_db') as mocked_get_object_from_db:
      mocked_get_object_from_db.side_effect = RuntimeError('a message')
      self.assertEqual(some_method(), False)

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

模拟现在是标准库的一部分。https://pypi.python.org/pypi/mock

这样做可以让您免于进行挡板测试。你知道那些随机失败的人。