我正在为Google App Engine应用程序(Python)编写一些单元测试。我正在使用mock库来模拟NDB tasklet。
但是,因为tasklet返回Future对象,我想知道如何实例化并使用我自己的自定义NDB Future对象,我可以将其作为mock的行为的一部分返回。如果没有这种能力,我完全不知道如何模拟ndb tasklet以验证在tasklet中调用了正确的方法。
在这个例子中。 async_datastore_update()用@ ndb.toplevel修饰。在这个函数内部,有一个我要模拟的NDB tasklet:yield self._async_get_specialist(specialist_name)
a_mgr = data_manager.AchievementsHandler()
# Initiate data store sync and flush async to force result
future = a_mgr.async_datastore_update()
future.get_result() # Flushes out the self.async_get_specialist() tasklet's results
# Continue testing...
没有模拟self.async_get_specialist()
,这可以通过刷新顶级函数中的异步进程来实现。
然而,当我嘲笑self.async_get_specialist()
来验证行为时,我在调用未来的get_result()
方法时遇到异常:
# Here, we mock out a future object, as per GAE docs
promise_obj_stub = ndb.Future()
a_mgr = data_manager.AchievementsHandler()
a_mgr._async_get_specialist = mock.Mock(return_value=promise_obj_stub)
# Initiate data store sync and flush async to force result
future = a_mgr.async_datastore_update()
future.get_result() # Throws a RuntimeError exception b/c result is never assigned to the Future object
App Engine docs似乎没有表明除了检查来自GAE api的结果之外,还有一种方法可以使用Future对象。即我在文档中看不到Future.set_return_value()的影响。
有人知道a)单元测试tasklets的最佳方法吗?或者b)假设我的方法有意义,如何将值传递给ndb Future对象?
答案 0 :(得分:5)
set_result()
方法,可以将您自己的信息传递给将来(目前在GAE Future class docs上未列出。因此,以下代码可以正常工作奇妙:
# Here, we mock out a future object, as per GAE docs
promise_obj_stub = ndb.Future()
a_mgr = data_manager.AchievementsHandler()
a_mgr._async_get_specialist = mock.Mock(return_value=promise_obj_stub)
# Initiate data store sync and flush async to force result
future = a_mgr.async_datastore_update()
promise_obj_stub.set_result(['list', 'of', 'results', 'i', 'needed']) # set a result on the Future obj
future.get_result() # Works like a charm now
# Continue testing as usual
答案 1 :(得分:1)
接受的答案效果很好,但我想添加我用于其他读者的方法。
我通常做的是创建一个像MockFuture这样的简单对象:
class MockFuture(object):
def __init__(self, data=None):
self.data = data
def get_result(self):
return self.data
这允许您在创建我发现更自然的未来时设置数据。
future = MockFuture(data=432)
另外一条评论,这在测试情况之外也很有用。有时你有一些条件逻辑,如果你实际上进行异步调用,你想要None(或其他)。在这种情况下,您可以使用MockFuture(也可以使用已接受的答案),以便处理结果的代码不必检查对象或类似的东西,它只是调用get_result()而不管事情是如何设置的