在测试时模拟 Oauth 提供者

Posted

技术标签:

【中文标题】在测试时模拟 Oauth 提供者【英文标题】:Mocking Oauth providers while testing 【发布时间】:2013-09-20 14:25:31 【问题描述】:

我正在编写一个应用程序,它针对 Oauth 2.0 授权服务器进行身份验证。我想测试只有在您登录后才能访问的部分,但 Oauth 服务器是一个外部依赖项,它使我的测试变得复杂和脆弱。

关于我应该如何处理这件事有什么建议吗?对于这样的事情,行业的做法是什么?我的直觉是以某种方式模拟服务器,以便它允许访问受保护的资源。

如果重要的话,这是一个使用 Flask 编写的 Python webapp。

我正在使用一个自定义的 oauth 服务器,它将在我自己的域上运行,虽然可以按照 FoxMask 的建议添加某种沙盒功能,但我更希望能够运行测试而不需要运行额外的服务器.

【问题讨论】:

通常,“外部”Oauth(如 Twitter、Evernote 等服务)提供了一个沙箱来进行我们的测试。您没有为此目的找到一个吗? 但他们仍然要求您对他们进行身份验证?只是他们向您发送了测试的虚拟凭据? 是的,他们当然需要。是的,他们返回了一个虚拟凭据或等效凭据。例如,Evernote 提供了仅用于测试目的的特殊键。这就是使用 API 完成我们的开发的诀窍。一旦您将开发人员卷曲以推动生产,您将获得用于生产的新 api 密钥。 我的 Oauth2 提供程序是在我自己的机器上运行的 custom server。我可以在其中添加此功能,但我更希望能够在不需要实际运行的 Oauth 服务器的情况下运行测试。 我明白了,你应该从这个细节开始。我会避免为你谈论无用的事情;)所以我们现在回到起点。对不起。 【参考方案1】:

从消费者(即您的应用程序)方面来看,OAuth2 流程可以分为两部分:

    从您的应用程序重定向到 OAuth2 提供者的“授权”URL 将 OAuth2 提供程序返回的“代码”交换为访问令牌

对于#1,您需要测试的是,当您调用启动身份验证过程的路由时,返回的响应是重定向到 OAuth2 提供程序。这可以通过 Flask 的test client 轻松完成。响应应具有 302 的状态代码和设置为 OAuth2 提供程序的授权 URL 的“位置”标头。请注意,您不需要提供程序启动,您只是测试响应是重定向,但您不需要实际重定向。

#2 的测试涉及更多一点。您的 Flask 应用程序有一个特殊的 URL,该 URL 被指定为 OAuth2 提供程序的“重定向 URL”,以将授权代码发回给您。您可以使用传递模拟代码的 Flask 测试客户端调用此 URL,这没有问题。

问题在于,在处理重定向 URL 的视图函数中,您需要调用 OAuth2 提供程序以将身份验证代码交换为访问令牌,并且这是同步完成的。为防止此事务发生,您必须检查 app.config['TESTING'],在这种情况下跳过实际请求并将其替换为包含模拟访问令牌的虚假响应。

从那时起,您还需要伪造对发送访问令牌以请求数据的 OAuth2 提供程序的任何其他调用。

如果您在 Flask 应用程序中使用 OAuth2 客户端库,则无需在应用程序中创建测试异常就可以更轻松地创建模拟提供程序。在我的例子中,我使用rauth,为此我创建了OAuth2Service 类的子类,它覆盖了正确的方法并使用我从真实会话中捕获的模拟数据进行响应。然后在我的测试设置中,我只是创建了模拟服务,应用程序被愚弄以为它正在与真实的服务器通信。

我希望这会有所帮助。

【讨论】:

因此,为了子类化 OAuth2Service,您必须充分分离会话的创建,以便您可以指定为测试实例化哪个版本的 OAuth2Service?

以上是关于在测试时模拟 Oauth 提供者的主要内容,如果未能解决你的问题,请参考以下文章

在 Laravel 中运行功能测试时如何模拟服务(或服务提供者)?

如何在 IOS5 模拟器上获取 Facebook 应用程序?

如何提供模拟实体管理器来测试服务类?

测试组件时如何模拟管道

使用 Grails 实现 OAuth2 提供程序

StarWind模拟iscsi设备 为vmware测试提供共享存储