1

我有一个方法运行在一个单独的线程,这有一些联系人匹配。Django unittesting:model.all()查询集在单独线程中运行的方法是空的

我在写测试以检查联系人是否已同步。测试用例是这样的:

class ContactSyncTestCase(TestCase): 
    fixtures = ['fix.json'] 

    def setUp(self): 
     # get a few contacts that exist in the database to be sent for matching 
     self.few_contacts = CompanyContact.objects.all().order_by('?')[:5].values_list('contact_number',flat=True) 

    def test_submit_contacts(self): 

     # Pick up a random user 
     user = User.objects.all().order_by('?')[0] 

     # Get API Key for that user 
     key = ApiKey.objects.get(user=user).key 

     # The url that submits contacts for matching, returns a matching key immediately and starts a separate thread to sync contacts 
     sync_request_url = '/sync_contacts/?username=%s&api_key=%s'%(user.username,key) 
     sync_request_response = self.client.post(path=sync_request_url, 
            data=json.dumps({"contacts":','.join(self.few_contacts)}), 
            content_type="application/json") 

     # Key that is used to fetch the status of contacts syncing and returns a json if contacts are matched 
     key = sync_request_response.content 

     # At this point, the other thread is doing the task of syncing inside the method mentioned next 

     # Hence I put the test on pause so that it does not fail and exit 
     try: 
      while True: 
       time.sleep(100) 
     except KeyboardInterrupt: 
      pass 

这些数字相匹配的异步方法开始是这样的:

def match_numbers(key, contacts, user): 
    # Get all contacts stored in the system 
    """ 

    :param key: 
    :param contacts: 
    :param user: 
    """ 
    import pdb;pdb.set_trace() 
    system_contacts = CompanyContact.objects.all().values_list('contact_number', flat=True) 

现在,这里的奇怪的问题是:

CompanyContact.objects.all().values_list('contact_number', flat=True) 

返回测试时一个空的查询集。但是,在运行时它工作正常。

对于这个问题,任何查询(包括用户模型)都返回一个空的查询集。

任何想法为什么?

编辑:

原来,从TrasactionTestCase继承解决了这个问题。我仍然怀疑,并且为了同样的目的,我挖了更多。

我的数据库的默认事务级别是可重复读取。

this post阅读,

重复读取(默认):保证是事务发出相同的两次选择,它得到了同样的结果两次,而不管其它事务做出提交或提交的更改。换句话说,它从相同查询的不同执行中获得一致的结果。在某些数据库系统中,REPEATABLE READ隔离级别允许幻影,因此如果另一个事务插入新行,则在SELECT语句之间的间隔中,第二个SELECT将会看到它们。 InnoDB不是这样; REPEATABLE READ级别不出现幻影。

总结:我应该还是得到了现有的记录,但我没有。

+1

尝试使用TransactionTestCase,看到http://stackoverflow.com/a/10949616/1423473 – erthalion

+0

这一工程! TransactionTestCase。但是,我不知道为什么它不会抛出一个错误,但返回一个空的查询集。 –

+0

它返回一个空的查询集,因为它试图直接连接到数据库,而所有的测试数据保存在内存中。 – erthalion

回答

2

你可以在Django中找到一个很好的解释LiveServerTestCase

class LiveServerTestCase(TransactionTestCase): 
    """ 
    ... 
    Note that it inherits from TransactionTestCase instead of TestCase because 
    the threads do not share the same transactions (unless if using in-memory 
    sqlite) and each thread needs to commit all their transactions so that the 
    other thread can see the changes. 
    """ 
+0

这绝对是一个好点。然而,它说:“每个线程需要提交所有事务,以便其他线程可以看到更改”。但是,在这种情况下,我甚至无法在加载灯具时看到最初的数据。 –

+0

我想我明白了。基本上,在TestCase的情况下,夹具正在被加载到该特定事务中,因此根据这部分文档,另一个线程看不到这个,因为夹具完全没有被提交。 听起来合法吗? –

+0

是的,当然 - 因为夹具加载与测试体中通常的数据保存没有区别。 – erthalion

相关问题