我有一个UserRepository类,我正在为
编写单元测试class UserRepository(object):
"""
Repository that handles storage and retrieval of models.User objects
in and from the datastore.
"""
def create(self, user):
"""
Create the given user in the datastore if it doesn't exist yet.
Args:
user: The user to create.
Returns:
The created user.
Raises:
exc.DuplicateEntity: If the desired phonenumber is
already taken.
"""
duplicate_user = models.User.query(models.User.phonenumber == user.phonenumber).fetch()
if duplicate_user:
raise exc.DuplicateEntity()
user.put()
return user
我有这些测试
class UserServiceTest(unittest.TestCase):
"""Tests for the UserService."""
def setUp(self):
"""
Called before tests are run.
"""
self.user_repo = repositories.UserRepository()
#self.policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(probability=1)
def test_create(self):
"""
Test if the create method creates a user.
"""
ndb.delete_multi(models.User.query().fetch(keys_only=True))
user = models.User(phonenumber='+31612345678#',
email='tim@castelijns.nl',
password='1234abcd')
ret_user = self.user_repo.create(user)
self.assertEqual(ret_user, user)
def test_create_duplicate_fails(self):
"""
Test if attempting to create a user with an existing phonenumber
fails.
"""
ndb.delete_multi(models.User.query().fetch(keys_only=True))
user = models.User(phonenumber='+31612345678#',
email='tim@castelijns.nl',
password='1234abcd')
self.user_repo.create(user)
with self.assertRaises(exc.DuplicateEntity):
self.user_repo.create(user)
ndb.delete_multi(models.User.query().fetch(keys_only=True))
用于清除测试环境中的现有用户,因此测试用例不会相互影响。
这是自定义异常
class DuplicateEntity(Exception):
"""Exception to raise when trying to create a duplicate entity."""
我用
运行测试$ nosetests --with-gae
输出
======================================================================
FAIL: Test if attempting to create a user with an existing phonenumber
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tests/dal/test_repositories.py", line 53, in test_create_duplicate_fails
self.user_repo.create(user)
AssertionError: DuplicateEntity not raised
----------------------------------------------------------------------
Ran 2 tests in 0.080s
FAILED (failures=1)
这是意料之外的,因为此处对.create的第二次调用应该引发异常,因为已经有一个用户拥有该phonenumber。
我确信代码有效,因为我已经对它进行了实时测试。
如果我在with语句之上添加对.create的调用,它会引发异常,这也很奇怪:
self.user_repo.create(user)
self.user_repo.create(user)
with self.assertRaises(exc.DuplicateEntity):
self.user_repo.create(user)
所以它在第3次通话时被提出,但不是第2次。
我感觉它与数据存储一致性策略有关,正如文档here所述:
然而,我不知道nosegae如何处理这个问题。它甚至可以配置吗? nosegae doesn't have alot of documentationPseudoRandomHRConsistencyPolicy类允许您控制 在每个全球(非祖先)之前申请写入的可能性 查询。通过将概率设置为0%,我们正在指示 数据存储存根以最大的最终数量运行 一致性。最大的最终一致性意味着写入将提交但是 始终无法应用,因此全局(非祖先)查询将会 始终没有看到变化。
我该如何解决(或修复)这个问题?
答案 0 :(得分:2)
您的问题是您正在使用查询来测试重复项,并且由于最终的一致性而无法保证能够正常运行。您将注意到,您引用的文档中的测试都使用了祖先查询,这些查询确保了一致性。
我的看法是这样,它是预期和正确的行为(AssertionError:DuplicateEntity not raise error)并突出显示模型/方法的问题。