我有一个棘手的问题,我似乎无法掌握。我是 ,目前正在编写一个django自定义auth-backend的单元测试。在我们的 系统中,我们实际上有两个后端:一个是内置的django后端 以及将请求发送到基于Java的API 的自定义后端,该后端以XML形式返回用户信息。现在,我正在写单元 测试,所以我不想在系统之外发送请求,如 ,我没有试图测试Java API,所以我的问题是我怎么能 解决这个问题,并嘲笑以最稳健的方式提供副作用。干净地嘲笑Django Unittests的远程服务器和API
我测试的功能是这样的,其中URL 设置值只是针对 验证用户名和密码的数据,并返回XML的Java服务器的基本URL,以及服务价值是 只是一些魔法建设的网址查询,它不重要的 我们:
@staticmethod
def get_info_from_api_with_un_pw(username, password, service=12345):
url = settings.AUTHENTICATE_URL_VIA_PASSWORD
if AUTH_FIELD == "username":
params = {"nick": username, "password": password}
elif AUTH_FIELD == "email":
params = {"email": username, "password": password}
params["service"] = service
encoded_params = urlencode([(k, smart_str(v, "latin1")) for k, v in params.items()])
try:
# get the user's data from the api
xml = urlopen(url + encoded_params).read()
userinfo = dict((e.tag, smart_unicode(e.text, strings_only=True))
for e in ET.fromstring(xml).getchildren())
if "nil" in userinfo:
return userinfo
else:
return None
所以,我们得到的XML,解析成一个字典,如果关键的零存在 那么我们可以返回字典和发扬快乐并经过认证。 显然,一个解决方案是只是为了找到猴补丁在XML变量的逻辑,我发现这个答案的方式以某种方式覆盖或 :
How can one mock/stub python module like urllib
我试图实现类似的东西,但在细节上有是 非常粗略,我似乎无法得到这个工作。
我也拍摄到的XML响应,并把它放在一个本地文件中 测试文件夹寻找一种方法来使用,作为传递到测试功能的URL参数模拟 响应的意图, 像这样将覆盖网址:
@override_settings(AUTHENTICATE_URL_VIA_PASSWORD=(os.path.join(os.path.dirname(__file__), "{0}".format("response.xml"))))
def test_get_user_info_username(self):
self.backend = RemoteAuthBackend()
self.backend.get_info_from_api_with_un_pw("user", "pass")
但也需要考虑到的是, 函数定义(即“URL + encoded_params”)的URL建筑逻辑。再次,我可以将 的响应文件重命名为与连接的url相同,但这不像是一个很好的函数单元测试和更多的“作弊”,整个 事情越来越多这些解决方案一直都很脆弱,无论如何它只是一个固定装置,这也是我想要尽量避免的东西。
我也想知道是否有一种方法可以在django开发服务器上为xml服务,然后在那里指向这个函数?这似乎是一个更为理智的解决方案,但是如果这样的事情是可能的或者明智的,那么很多使用Google的人不会给我提供任何线索,即使如此,我也认为这不是一种在开发环境之外运行的测试。
所以,理想情况下,我需要能够以某种方式嘲笑“服务器”,以 采取了Java API的地方在函数调用,或以某种方式成为 一些XML负载的功能,可以作为其网址打开,或 monkeatch从测试本身的功能,或...
模拟库是否有适当的工具来做这样的事情?
http://www.voidspace.org.uk/python/mock
那么,有两点对这个问题1)我想解决一个干净的方式我 特别的问题,更重要的是2)什么是 的最佳做法干净写Django的单元 - 根据数据,Cookie等, 进行测试,以便从远程的 API进行用户验证,该API位于您的域之外?
在你的情况下,你会想要模拟以下内容:'import models; self.mock('models.urlopen')',因为它似乎是在您的模型文件'urllib import urlopen'中将它导入如下。 – Pykler
啊,那太棒了,看起来这样的嘲笑就是票。非常感谢! – osman