diff --git a/appveyor.test.ps1 b/appveyor.test.ps1
index 4fa1c7b0..d7223364 100644
--- a/appveyor.test.ps1
+++ b/appveyor.test.ps1
@@ -38,7 +38,7 @@
function runUnitTest() {
write-host "dotnet test test\UnitTest" -ForegroundColor Cyan
- dotnet test test\UnitTest --filter "FullyQualifiedName!~MySql" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Include="[Bootstrap*]*" /p:ExcludeByFile="..\..\src\admin\Bootstrap.Admin\Program.cs%2c..\..\src\admin\Bootstrap.Admin\Startup.cs%2c..\..\src\admin\Bootstrap.Admin\HttpHeaderOperation.cs" /p:CoverletOutput=..\..\
+ dotnet test test\UnitTest --filter="FullyQualifiedName!~MySql" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Include="[Bootstrap.Admin*]*%2c[Bootstrap.DataAccess*]*" /p:Exclude="[*]*Program%2c[*]*Startup%2c[Bootstrap.DataAccess]*AutoDB%2c[Bootstrap.DataAccess]*WeChatHelper%2c[Bootstrap.DataAccess]*DbLogTask" /p:ExcludeByFile="**/SMSExtensions.cs%2c**/Helper/OAuthHelper.cs" /p:CoverletOutput=..\..\
}
function coverallUnitTest() {
diff --git a/appveyor.yml b/appveyor.yml
index c44b5534..cf7a0c69 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -24,7 +24,11 @@ services:
- mongodb
install:
- ps: >-
+ #copy my.ini into mysql folder
+
dotnet --version
+
+ #xcopy "$($env:appveyor_build_folder)\db\MySQL\my.ini" "C:\Program Files\MySQL\MySQL Server 5.7" /y
build_script:
- ps: >-
.\appveyor.build.ps1
diff --git a/db/MySQL/my.ini b/db/MySQL/my.ini
index eb91891f..9f4ad7e2 100644
--- a/db/MySQL/my.ini
+++ b/db/MySQL/my.ini
@@ -1,7 +1,9 @@
-[client]
+[client]
default-character-set=utf8
[mysqld]
charcater_set_client=utf8
character_set_connection=utf8
-character_set_results=utf8
\ No newline at end of file
+character_set_results=utf8
+character_set_server=utf8
+character_set_database=utf8
diff --git a/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj b/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj
index 09a783d9..d03fcff4 100644
--- a/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj
+++ b/src/admin/Bootstrap.Admin/Bootstrap.Admin.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/src/admin/Bootstrap.Admin/Controllers/Api/LoginController.cs b/src/admin/Bootstrap.Admin/Controllers/Api/LoginController.cs
index d0f3cb03..5aaea6cf 100644
--- a/src/admin/Bootstrap.Admin/Controllers/Api/LoginController.cs
+++ b/src/admin/Bootstrap.Admin/Controllers/Api/LoginController.cs
@@ -52,11 +52,7 @@ namespace Bootstrap.Admin.Controllers.Api
///
///
[HttpPut]
- public async Task Put([FromServices]ISMSProvider provider, [FromQuery]string phone)
- {
- if (string.IsNullOrEmpty(phone)) return false;
- return await provider.SendCodeAsync(phone);
- }
+ public async Task Put([FromServices]ISMSProvider provider, [FromQuery]string phone) => string.IsNullOrEmpty(phone) ? false : await provider.SendCodeAsync(phone);
///
/// 跨域握手协议
diff --git a/src/admin/Bootstrap.Admin/Extensions/HttpHeaderOperation.cs b/src/admin/Bootstrap.Admin/Extensions/HttpHeaderOperation.cs
index 5c9fae1f..f479233d 100644
--- a/src/admin/Bootstrap.Admin/Extensions/HttpHeaderOperation.cs
+++ b/src/admin/Bootstrap.Admin/Extensions/HttpHeaderOperation.cs
@@ -17,8 +17,6 @@ namespace Bootstrap.Admin
///
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
- if (operation.Parameters == null) operation.Parameters = new List();
-
if (context.MethodInfo.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Length == 0)
{
operation.Parameters.Add(new OpenApiParameter()
diff --git a/src/admin/Bootstrap.Admin/Extensions/SMSExtensions.cs b/src/admin/Bootstrap.Admin/Extensions/SMSExtensions.cs
index 33b31aac..331dc57a 100644
--- a/src/admin/Bootstrap.Admin/Extensions/SMSExtensions.cs
+++ b/src/admin/Bootstrap.Admin/Extensions/SMSExtensions.cs
@@ -1,6 +1,5 @@
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Options;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -241,7 +240,7 @@ namespace Microsoft.Extensions.DependencyInjection
///
/// 获得/设置 默认授权 App
///
- public string App { get; set; }
+ public string App { get; set; } = "0";
///
/// 获得/设置 短信下发网关地址
diff --git a/src/admin/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj b/src/admin/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj
index 69f28f73..236d7d29 100644
--- a/src/admin/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj
+++ b/src/admin/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/src/admin/Bootstrap.DataAccess/DbManager.cs b/src/admin/Bootstrap.DataAccess/DbManager.cs
index de5d18f9..5b482aa5 100644
--- a/src/admin/Bootstrap.DataAccess/DbManager.cs
+++ b/src/admin/Bootstrap.DataAccess/DbManager.cs
@@ -18,7 +18,7 @@ namespace Bootstrap.DataAccess
///
///
///
- /// 是否记录日志
+ /// 是否记录日志
///
public static IDatabase Create(string connectionName = null, bool keepAlive = false, bool enableLog = true)
{
diff --git a/src/admin/Bootstrap.DataAccess/Helper/LogHelper.cs b/src/admin/Bootstrap.DataAccess/Helper/LogHelper.cs
index 5d7ce218..cc7feaf0 100644
--- a/src/admin/Bootstrap.DataAccess/Helper/LogHelper.cs
+++ b/src/admin/Bootstrap.DataAccess/Helper/LogHelper.cs
@@ -81,7 +81,7 @@ namespace Bootstrap.DataAccess
while (_messageQueue.TryTake(out var log))
{
logs.Add(log);
- };
+ }
if (logs.Any())
{
using (var db = DbManager.Create(enableLog: false))
diff --git a/src/admin/Bootstrap.DataAccess/Helper/OAuthHelper.cs b/src/admin/Bootstrap.DataAccess/Helper/OAuthHelper.cs
index 0b143b83..42156b66 100644
--- a/src/admin/Bootstrap.DataAccess/Helper/OAuthHelper.cs
+++ b/src/admin/Bootstrap.DataAccess/Helper/OAuthHelper.cs
@@ -74,7 +74,7 @@ namespace Bootstrap.DataAccess
///
/// 插入 Gitee 授权用户到数据库中
///
- ///
+ ///
///
private static User ParseUser(OAuthCreatingTicketContext context)
{
diff --git a/src/admin/Bootstrap.DataAccess/Helper/WeChatHelper.cs b/src/admin/Bootstrap.DataAccess/Helper/WeChatHelper.cs
index eeb5b89a..a0400dd5 100644
--- a/src/admin/Bootstrap.DataAccess/Helper/WeChatHelper.cs
+++ b/src/admin/Bootstrap.DataAccess/Helper/WeChatHelper.cs
@@ -4,6 +4,9 @@ using Longbow.WeChatAuth;
using Microsoft.AspNetCore.Authentication.OAuth;
using System;
using System.Linq;
+#if NETCOREAPP3_0
+using System.Text.Json;
+#endif
namespace Bootstrap.DataAccess
{
@@ -35,7 +38,7 @@ namespace Bootstrap.DataAccess
///
/// 插入 Gitee 授权用户到数据库中
///
- ///
+ ///
///
private static User ParseUser(OAuthCreatingTicketContext context)
{
@@ -53,7 +56,7 @@ namespace Bootstrap.DataAccess
}
#if NETCOREAPP3_0
- private static T ToObject(this System.Text.Json.JsonElement element) where T : WeChatUser
+ private static T ToObject(this JsonElement element) where T : WeChatUser
{
var user = new WeChatUser();
var target = element.EnumerateObject();
@@ -70,7 +73,7 @@ namespace Bootstrap.DataAccess
return user as T;
}
- private static string TryGetValue(this System.Text.Json.JsonElement.ObjectEnumerator target, string propertyName)
+ private static string TryGetValue(this JsonElement.ObjectEnumerator target, string propertyName)
{
var ret = string.Empty;
var property = target.FirstOrDefault(t => t.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));
diff --git a/test/UnitTest/BAWebHost.cs b/test/UnitTest/BAWebHost.cs
index fafbc137..f8aa41c7 100644
--- a/test/UnitTest/BAWebHost.cs
+++ b/test/UnitTest/BAWebHost.cs
@@ -10,6 +10,8 @@ using System.Net;
using System.Net.Http;
using UnitTest;
using Xunit;
+using Microsoft.Extensions.DependencyInjection;
+using System.Threading.Tasks;
namespace Bootstrap.Admin
{
@@ -119,6 +121,39 @@ namespace Bootstrap.Admin
builder.ConfigureAppConfiguration(app => app.AddJsonFile(TestHelper.RetrievePath($"UnitTest{Path.DirectorySeparatorChar}appsettings.appveyor.json"), false, true));
}
TestHelper.ConfigureWebHost(builder);
+
+ // 替换 SMS 服务
+ builder.ConfigureServices(services =>
+ {
+ services.AddTransient();
+ });
+ }
+
+
+ ///
+ /// 手机号登陆帮助类
+ ///
+ class DefaultSMSProvider : ISMSProvider
+ {
+ ///
+ /// 获得 短信配置信息
+ ///
+ public SMSOptions Option { get; protected set; } = new SMSOptions();
+
+ ///
+ /// 下发验证码方法
+ ///
+ ///
+ ///
+ public Task SendCodeAsync(string phoneNumber) => Task.FromResult(true);
+
+ ///
+ /// 验证验证码方法
+ ///
+ /// 手机号
+ /// 验证码
+ ///
+ public bool Validate(string phone, string code) => code == "1234";
}
}
}
diff --git a/test/UnitTest/Bootstrap.Admin/Api/HttpHeaderOperationTest.cs b/test/UnitTest/Bootstrap.Admin/Api/HttpHeaderOperationTest.cs
new file mode 100644
index 00000000..12b34cec
--- /dev/null
+++ b/test/UnitTest/Bootstrap.Admin/Api/HttpHeaderOperationTest.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Mvc.ApiExplorer;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using Xunit;
+
+namespace Bootstrap.Admin.Api
+{
+ public class HttpHeaderOperationTest
+ {
+ [Fact]
+ public void Apply_Ok()
+ {
+ var oper = new HttpHeaderOperation();
+ var api = new OpenApiOperation();
+ var desc = new ApiDescription();
+ var mi = typeof(HttpHeaderOperationTest).GetMethod("Apply_Ok");
+ var context = new OperationFilterContext(desc, null, null, mi);
+ oper.Apply(api, context);
+ }
+ }
+}
diff --git a/test/UnitTest/Bootstrap.Admin/Api/SQLServer/LoginTest.cs b/test/UnitTest/Bootstrap.Admin/Api/SQLServer/LoginTest.cs
index df7d7e2d..e8b6dbd8 100644
--- a/test/UnitTest/Bootstrap.Admin/Api/SQLServer/LoginTest.cs
+++ b/test/UnitTest/Bootstrap.Admin/Api/SQLServer/LoginTest.cs
@@ -39,10 +39,9 @@ namespace Bootstrap.Admin.Api.SqlServer
var _token = await resq.Content.ReadAsStringAsync();
Assert.Equal("false", _token);
- // UNDONE: 重构短信登陆后完善
- //resq = await Client.PutAsync("?phone=", new StringContent(""));
- //_token = await resq.Content.ReadAsStringAsync();
- //Assert.Equal("true", _token);
+ resq = await Client.PutAsync("?phone=18910001000", new StringContent(""));
+ _token = await resq.Content.ReadAsStringAsync();
+ Assert.Equal("true", _token);
}
[Fact]
diff --git a/test/UnitTest/Bootstrap.Admin/Controllers/SQLServer/AccountTest.cs b/test/UnitTest/Bootstrap.Admin/Controllers/SQLServer/AccountTest.cs
index 1ebe11f9..e682c273 100644
--- a/test/UnitTest/Bootstrap.Admin/Controllers/SQLServer/AccountTest.cs
+++ b/test/UnitTest/Bootstrap.Admin/Controllers/SQLServer/AccountTest.cs
@@ -1,10 +1,8 @@
using Bootstrap.DataAccess;
using System;
-using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Http;
-using System.Reflection;
using Xunit;
namespace Bootstrap.Admin.Controllers.SqlServer
@@ -123,22 +121,54 @@ namespace Bootstrap.Admin.Controllers.SqlServer
}
[Fact]
- public void Mobile_Ok()
+ public async void Mobile_Ok()
{
- // UNDONE: Mobile 单元测试未完成
+ using (var db = DbManager.Create()) db.Execute("delete from Users where UserName = @0", "18910001000");
+ var client = Host.CreateClient();
+ var r = await client.GetAsync("/Account/Login");
+ var view = await r.Content.ReadAsStringAsync();
+ var tokenTag = "");
+ var antiToken = view.Substring(0, index);
- // 反射设置 SMSHelper 内部验证码保证 Validate 方法返回真
- var validateCodeInstance = Activator.CreateInstance(Type.GetType("Bootstrap.DataAccess.SMSHelper+AutoExpireValidateCode, Bootstrap.DataAccess"), new object[] { "18910001000", "1234", TimeSpan.FromSeconds(10)});
- var _poolInstance = typeof(SMSHelper).GetField("_pool", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
- //_pool.AddOrUpdate(option.Phone, key => new AutoExpireValidateCode(option.Phone, result.Data, option.Expires), (key, v) => v.Reset(result.Data));
- //var addMethod = _poolInstance.GetType().GetMethod("AddOrUpdate");
- //addMethod.Invoke(_poolInstance, new object[] { "18910001000", validateCodeInstance, null });
+ var content = new MultipartFormDataContent
+ {
+ { new StringContent("18910001000"), "phone" },
+ { new StringContent("1234"), "code" },
+ { new StringContent(antiToken), "__RequestVerificationToken" }
+ };
+ var m = await client.PostAsync("/Account/Mobile", content);
+ Assert.True(m.IsSuccessStatusCode);
+ var payload = await r.Content.ReadAsStringAsync();
+ Assert.Contains("登 录", payload);
+ }
- //var client = Host.CreateClient();
- //var r = await client.GetAsync($"/Account/Mobile?phone=18910001000&code=1234");
- //Assert.True(r.IsSuccessStatusCode);
- //var content = await r.Content.ReadAsStringAsync();
- //Assert.Contains("登 录", content);
+ [Fact]
+ public async void Mobile_Fail()
+ {
+ using (var db = DbManager.Create()) db.Execute("delete from Users where UserName = @0", "18910001000");
+
+ var client = Host.CreateClient();
+ var r = await client.GetAsync("/Account/Login");
+ var view = await r.Content.ReadAsStringAsync();
+ var tokenTag = "");
+ var antiToken = view.Substring(0, index);
+
+ var content = new MultipartFormDataContent
+ {
+ { new StringContent("18910001000"), "phone" },
+ { new StringContent("1000"), "code" },
+ { new StringContent(antiToken), "__RequestVerificationToken" }
+ };
+ var m = await client.PostAsync("/Account/Mobile?AppId=0", content);
+ Assert.True(m.IsSuccessStatusCode);
+ var payload = await r.Content.ReadAsStringAsync();
+ Assert.Contains("登 录", payload);
}
}
}
diff --git a/test/UnitTest/Bootstrap.DataAccess/MongoDB/DBLogTest.cs b/test/UnitTest/Bootstrap.DataAccess/MongoDB/DBLogTest.cs
new file mode 100644
index 00000000..47ff8061
--- /dev/null
+++ b/test/UnitTest/Bootstrap.DataAccess/MongoDB/DBLogTest.cs
@@ -0,0 +1,14 @@
+using Xunit;
+
+namespace Bootstrap.DataAccess.MongoDB
+{
+ [Collection("MongoContext")]
+ public class DBLogTest : SqlServer.DBLogTest
+ {
+ [Fact]
+ public override void Save_Ok()
+ {
+ Assert.True(new DBLog().Save(null));
+ }
+ }
+}
diff --git a/test/UnitTest/Bootstrap.DataAccess/MySql/DBLogTest.cs b/test/UnitTest/Bootstrap.DataAccess/MySql/DBLogTest.cs
new file mode 100644
index 00000000..3692ecf8
--- /dev/null
+++ b/test/UnitTest/Bootstrap.DataAccess/MySql/DBLogTest.cs
@@ -0,0 +1,10 @@
+using Xunit;
+
+namespace Bootstrap.DataAccess.MySql
+{
+ [Collection("MySqlContext")]
+ public class DBLogTest : SqlServer.DBLogTest
+ {
+
+ }
+}
diff --git a/test/UnitTest/Bootstrap.DataAccess/SQLServer/DBLogTest.cs b/test/UnitTest/Bootstrap.DataAccess/SQLServer/DBLogTest.cs
new file mode 100644
index 00000000..9c2bf32a
--- /dev/null
+++ b/test/UnitTest/Bootstrap.DataAccess/SQLServer/DBLogTest.cs
@@ -0,0 +1,28 @@
+using System;
+using Xunit;
+
+namespace Bootstrap.DataAccess.SqlServer
+{
+ [Collection("SQLServerContext")]
+ public class DBLogTest
+ {
+ [Fact]
+ public virtual void Save_Ok()
+ {
+ var log = new DBLog()
+ {
+ Id = "",
+ LogTime = DateTime.Now,
+ SQL = "UnitTest",
+ UserName = "UniTest"
+ };
+ Assert.True(log.Save(log));
+ }
+
+ [Fact]
+ public void Save_Exception()
+ {
+ Assert.Throws(() => new DBLog().Save(null));
+ }
+ }
+}
diff --git a/test/UnitTest/Bootstrap.DataAccess/SQLite/DBLogTest.cs b/test/UnitTest/Bootstrap.DataAccess/SQLite/DBLogTest.cs
new file mode 100644
index 00000000..40ded307
--- /dev/null
+++ b/test/UnitTest/Bootstrap.DataAccess/SQLite/DBLogTest.cs
@@ -0,0 +1,10 @@
+using Xunit;
+
+namespace Bootstrap.DataAccess.SQLite
+{
+ [Collection("SQLiteContext")]
+ public class DBLogTest : SqlServer.DBLogTest
+ {
+
+ }
+}