You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ReviewAndAnalyzeOpenSourceS.../src/DjangoBlog/oauth/tests.py

325 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""lrj
OAuth 认证测试模块
包含OAuth配置、登录流程和各平台OAuth功能的单元测试
"""
import json
from unittest.mock import patch
from django.conf import settings
from django.contrib import auth
from django.test import Client, RequestFactory, TestCase
from django.urls import reverse
from djangoblog.utils import get_sha256
from oauth.models import OAuthConfig
from oauth.oauthmanager import BaseOauthManager
# Create your tests here.
class OAuthConfigTest(TestCase):
"""lrj
OAuth配置模型测试类
测试OAuth配置相关的功能
"""
def setUp(self):
"""lrj测试初始化设置"""
self.client = Client() # lrjDjango测试客户端
self.factory = RequestFactory() # lrj请求工厂
def test_oauth_login_test(self):
"""lrj测试OAuth登录流程"""
# lrj创建微博OAuth配置
c = OAuthConfig()
c.type = 'weibo'
c.appkey = 'appkey'
c.appsecret = 'appsecret'
c.save()
# lrj测试OAuth登录重定向
response = self.client.get('/oauth/oauthlogin?type=weibo')
self.assertEqual(response.status_code, 302) # lrj验证重定向状态码
self.assertTrue("api.weibo.com" in response.url) # lrj验证重定向到微博授权页面
# lrj测试授权回调处理
response = self.client.get('/oauth/authorize?type=weibo&code=code')
self.assertEqual(response.status_code, 302) # lrj验证重定向状态码
self.assertEqual(response.url, '/') # lrj验证重定向到首页
class OauthLoginTest(TestCase):
"""lrj
OAuth登录流程测试类
测试各平台OAuth登录的完整流程
"""
def setUp(self) -> None:
"""lrj测试初始化设置"""
self.client = Client() # lrjDjango测试客户端
self.factory = RequestFactory() # lrj请求工厂
self.apps = self.init_apps() # lrj初始化所有OAuth应用配置
def init_apps(self):
"""lrj初始化所有OAuth平台配置"""
# lrj获取所有OAuth管理器子类并实例化
applications = [p() for p in BaseOauthManager.__subclasses__()]
for application in applications:
# lrj为每个平台创建配置
c = OAuthConfig()
c.type = application.ICON_NAME.lower() # lrj平台类型
c.appkey = 'appkey' # lrj测试用AppKey
c.appsecret = 'appsecret' # lrj测试用AppSecret
c.save()
return applications
def get_app_by_type(self, type):
"""lrj根据平台类型获取对应的OAuth应用"""
for app in self.apps:
if app.ICON_NAME.lower() == type:
return app
@patch("oauth.oauthmanager.WBOauthManager.do_post")
@patch("oauth.oauthmanager.WBOauthManager.do_get")
def test_weibo_login(self, mock_do_get, mock_do_post):
"""lrj测试微博OAuth登录流程"""
# lrj获取微博OAuth应用
weibo_app = self.get_app_by_type('weibo')
assert weibo_app #lrj 验证应用存在
# lrj测试授权URL生成
url = weibo_app.get_authorization_url()
# lrj模拟微博API响应
mock_do_post.return_value = json.dumps({"access_token": "access_token",
"uid": "uid"
})
mock_do_get.return_value = json.dumps({
"avatar_large": "avatar_large",
"screen_name": "screen_name",
"id": "id",
"email": "email",
})
# lrj测试获取访问令牌和用户信息
userinfo = weibo_app.get_access_token_by_code('code')
self.assertEqual(userinfo.token, 'access_token') # lrj验证访问令牌
self.assertEqual(userinfo.openid, 'id') #lrj 验证用户OpenID
@patch("oauth.oauthmanager.GoogleOauthManager.do_post")
@patch("oauth.oauthmanager.GoogleOauthManager.do_get")
def test_google_login(self, mock_do_get, mock_do_post):
"""lrj测试Google OAuth登录流程"""
# lrj获取Google OAuth应用
google_app = self.get_app_by_type('google')
assert google_app # lrj验证应用存在
# lrj测试授权URL生成
url = google_app.get_authorization_url()
# lrj模拟Google API响应
mock_do_post.return_value = json.dumps({
"access_token": "access_token",
"id_token": "id_token",
})
mock_do_get.return_value = json.dumps({
"picture": "picture",
"name": "name",
"sub": "sub",
"email": "email",
})
token = google_app.get_access_token_by_code('code')
userinfo = google_app.get_oauth_userinfo()
self.assertEqual(userinfo.token, 'access_token') # lrj验证访问令牌
self.assertEqual(userinfo.openid, 'sub') # lrj验证用户OpenID
@patch("oauth.oauthmanager.GitHubOauthManager.do_post")
@patch("oauth.oauthmanager.GitHubOauthManager.do_get")
def test_github_login(self, mock_do_get, mock_do_post):
"""测试GitHub OAuth登录流程"""
# lrj获取GitHub OAuth应用
github_app = self.get_app_by_type('github')
assert github_app # lrj验证应用存在
# lrj测试授权URL生成
url = github_app.get_authorization_url()
self.assertTrue("github.com" in url) # lrj验证GitHub域名
self.assertTrue("client_id" in url) #lrj 验证包含client_id参数
# lrj模拟GitHub API响应
mock_do_post.return_value = "access_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&scope=repo%2Cgist&token_type=bearer"
mock_do_get.return_value = json.dumps({
"avatar_url": "avatar_url",
"name": "name",
"id": "id",
"email": "email",
})
token = github_app.get_access_token_by_code('code')
userinfo = github_app.get_oauth_userinfo()
self.assertEqual(userinfo.token, 'gho_16C7e42F292c6912E7710c838347Ae178B4a') # lrj验证访问令牌
self.assertEqual(userinfo.openid, 'id') # lrj验证用户OpenID
@patch("oauth.oauthmanager.FaceBookOauthManager.do_post")
@patch("oauth.oauthmanager.FaceBookOauthManager.do_get")
def test_facebook_login(self, mock_do_get, mock_do_post):
"""lrj测试Facebook OAuth登录流程"""
# lrj获取Facebook OAuth应用
facebook_app = self.get_app_by_type('facebook')
assert facebook_app # lrj验证应用存在
# lrj测试授权URL生成
url = facebook_app.get_authorization_url()
self.assertTrue("facebook.com" in url) # lrj验证Facebook域名
# lrj模拟Facebook API响应
mock_do_post.return_value = json.dumps({
"access_token": "access_token",
})
mock_do_get.return_value = json.dumps({
"name": "name",
"id": "id",
"email": "email",
"picture": {
"data": {
"url": "url"
}
}
})
token = facebook_app.get_access_token_by_code('code')
userinfo = facebook_app.get_oauth_userinfo()
self.assertEqual(userinfo.token, 'access_token') # lrj验证访问令牌
@patch("oauth.oauthmanager.QQOauthManager.do_get", side_effect=[
'access_token=access_token&expires_in=3600', # lrj获取token响应
'callback({"client_id":"appid","openid":"openid"} );', # lrj获取openid响应
json.dumps({
"nickname": "nickname",
"email": "email",
"figureurl": "figureurl",
"openid": "openid",
}) # lrj获取用户信息响应
])
def test_qq_login(self, mock_do_get):
"""lrj测试QQ OAuth登录流程"""
# lrj获取QQ OAuth应用
qq_app = self.get_app_by_type('qq')
assert qq_app # lrj验证应用存在
# lrj测试授权URL生成
url = qq_app.get_authorization_url()
self.assertTrue("qq.com" in url) # lrj验证QQ域名
# lrj测试获取访问令牌和用户信息使用side_effect模拟多次调用
token = qq_app.get_access_token_by_code('code')
userinfo = qq_app.get_oauth_userinfo()
self.assertEqual(userinfo.token, 'access_token') # lrj验证访问令牌
@patch("oauth.oauthmanager.WBOauthManager.do_post")
@patch("oauth.oauthmanager.WBOauthManager.do_get")
def test_weibo_authoriz_login_with_email(self, mock_do_get, mock_do_post):
"""lrj测试带邮箱的微博授权登录完整流程"""
# lrj模拟微博API响应
mock_do_post.return_value = json.dumps({"access_token": "access_token",
"uid": "uid"
})
mock_user_info = {
"avatar_large": "avatar_large",
"screen_name": "screen_name1",
"id": "id",
"email": "email",
}
mock_do_get.return_value = json.dumps(mock_user_info)
# lrj测试OAuth登录重定向
response = self.client.get('/oauth/oauthlogin?type=weibo')
self.assertEqual(response.status_code, 302) # lrj验证重定向状态码
self.assertTrue("api.weibo.com" in response.url) # lrj验证重定向到微博
#lrj 测试授权回调处理
response = self.client.get('/oauth/authorize?type=weibo&code=code')
self.assertEqual(response.status_code, 302) #lrj 验证重定向状态码
self.assertEqual(response.url, '/') # lrj验证重定向到首页
# lrj验证用户已登录
user = auth.get_user(self.client)
assert user.is_authenticated # lrj验证用户已认证
self.assertTrue(user.is_authenticated)
self.assertEqual(user.username, mock_user_info['screen_name']) # lrj验证用户名
self.assertEqual(user.email, mock_user_info['email']) # lrj验证邮箱
# lrj登出用户
self.client.logout()
# lrj再次测试登录测试重复登录情况
response = self.client.get('/oauth/authorize?type=weibo&code=code')
self.assertEqual(response.status_code, 302) # lrj验证重定向状态码
self.assertEqual(response.url, '/') # lrj证重定向到首页
# lrj再次验证用户已登录
user = auth.get_user(self.client)
assert user.is_authenticated # lrj验证用户已认证
self.assertTrue(user.is_authenticated)
self.assertEqual(user.username, mock_user_info['screen_name']) # lrj验证用户名
self.assertEqual(user.email, mock_user_info['email']) # lrj验证邮箱
@patch("oauth.oauthmanager.WBOauthManager.do_post")
@patch("oauth.oauthmanager.WBOauthManager.do_get")
def test_weibo_authoriz_login_without_email(self, mock_do_get, mock_do_post):
"""lrj测试不带邮箱的微博授权登录完整流程需要补充邮箱"""
# lrj模拟微博API响应不含邮箱
mock_do_post.return_value = json.dumps({"access_token": "access_token",
"uid": "uid"
})
mock_user_info = {
"avatar_large": "avatar_large",
"screen_name": "screen_name1",
"id": "id",
}
mock_do_get.return_value = json.dumps(mock_user_info)
# lrj测试OAuth登录重定向
response = self.client.get('/oauth/oauthlogin?type=weibo')
self.assertEqual(response.status_code, 302) # lrj验证重定向状态码
self.assertTrue("api.weibo.com" in response.url) # lrj验证重定向到微博
# lrj测试授权回调处理应该重定向到邮箱补充页面
response = self.client.get('/oauth/authorize?type=weibo&code=code')
self.assertEqual(response.status_code, 302) # lrj验证重定向状态码
# lrj解析OAuth用户ID
oauth_user_id = int(response.url.split('/')[-1].split('.')[0])
self.assertEqual(response.url, f'/oauth/requireemail/{oauth_user_id}.html') #lrj 验证重定向到邮箱补充页面
# lrj测试邮箱补充表单提交
response = self.client.post(response.url, {'email': 'test@gmail.com', 'oauthid': oauth_user_id})
self.assertEqual(response.status_code, 302) # lrj验证重定向状态码
#lrj 生成安全签名
sign = get_sha256(settings.SECRET_KEY +
str(oauth_user_id) + settings.SECRET_KEY)
# lrj验证重定向到绑定成功页面
url = reverse('oauth:bindsuccess', kwargs={
'oauthid': oauth_user_id,
})
self.assertEqual(response.url, f'{url}?type=email')
# lrj测试邮箱确认链接
path = reverse('oauth:email_confirm', kwargs={
'id': oauth_user_id,
'sign': sign
})
response = self.client.get(path)
self.assertEqual(response.status_code, 302) #lrj 验证重定向状态码
self.assertEqual(response.url, f'/oauth/bindsuccess/{oauth_user_id}.html?type=success') #lrj 验证重定向到绑定成功页面
# lrj验证用户已登录
user = auth.get_user(self.client)
from oauth.models import OAuthUser
oauth_user = OAuthUser.objects.get(author=user)
self.assertTrue(user.is_authenticated) # lrj验证用户已认证
self.assertEqual(user.username, mock_user_info['screen_name']) # lrj验证用户名
self.assertEqual(user.email, 'test@gmail.com') #lrj 验证补充的邮箱
self.assertEqual(oauth_user.pk, oauth_user_id) # lrj验证OAuth用户ID匹配