单元测试:增加BootstrapAdmin工程Controller单元测试

This commit is contained in:
Argo-Surface 2019-01-16 12:17:08 +08:00
parent e90973b983
commit 969162a4ef
12 changed files with 303 additions and 75 deletions

View File

@ -0,0 +1,18 @@
using System.Net.Http;
using Xunit;
namespace Bootstrap.Admin.Api
{
public class ApiTest : IClassFixture<BAWebHost>
{
protected HttpClient Client { get; }
public ApiTest(BAWebHost factory, string view, bool login)
{
factory.ClientOptions.BaseAddress = new System.Uri($"http://localhost/api/{view}");
Client = factory.CreateClient();
if (login) factory.LoginAsync(Client).GetAwaiter();
}
}
}

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
using Xunit;
namespace Bootstrap.Admin.Api
{
public class CategoryTest : ApiTest
{
public CategoryTest(BAWebHost factory) : base(factory, "Category", false)
{
}
[Fact]
public async void Get_Ok()
{
var cates = await Client.GetAsJsonAsync<IEnumerable<string>>("");
Assert.NotEmpty(cates);
}
}
}

View File

@ -0,0 +1,37 @@
using Bootstrap.DataAccess;
using Bootstrap.Security;
using Longbow.Web.Mvc;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace Bootstrap.Admin.Api
{
public class DictsTest : ApiTest
{
public DictsTest(BAWebHost factory) : base(factory, "Dicts", true)
{
}
[Fact]
public async void Get_Ok()
{
// 菜单 系统菜单 系统使用条件
var query = "?sort=Category&order=asc&offset=0&limit=20&category=%E8%8F%9C%E5%8D%95&name=%E7%B3%BB%E7%BB%9F%E8%8F%9C%E5%8D%95&define=0&_=1547608210979";
var qd = await Client.GetAsJsonAsync<QueryData<BootstrapDict>>(query);
Assert.Single(qd.rows);
}
[Fact]
public async void PostAndDelete_Ok()
{
var ret = await Client.PostAsJsonAsync<BootstrapDict, bool>("", new BootstrapDict() { Name = "UnitTest-Dict", Category = "UnitTest-Category", Code = "0", Define = 0 });
Assert.True(ret);
var dict = new Dict();
var ids = dict.RetrieveDicts().Where(d => d.Name == "UnitTest-Dict").Select(d => d.Id);
Assert.True(await Client.DeleteAsJsonAsync<IEnumerable<string>, bool>("", ids));
}
}
}

View File

@ -0,0 +1,41 @@
using Bootstrap.DataAccess;
using Bootstrap.Security;
using Longbow.Web.Mvc;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using static Bootstrap.Admin.Controllers.Api.ExceptionsController;
namespace Bootstrap.Admin.Api
{
public class ExceptionsTest : ApiTest
{
public ExceptionsTest(BAWebHost factory) : base(factory, "Exceptions", true)
{
}
[Fact]
public async void Get_Ok()
{
// 菜单 系统菜单 系统使用条件
var query = "?sort=LogTime&order=desc&offset=0&limit=20&StartTime=&EndTime=&_=1547610349796";
var qd = await Client.GetAsJsonAsync<QueryData<BootstrapDict>>(query);
Assert.NotEmpty(qd.rows);
}
[Fact]
public async void Post_Ok()
{
var files = await Client.PostAsJsonAsync<string, IEnumerable<string>>("", string.Empty);
Assert.NotNull(files);
var fileName = files.FirstOrDefault();
if (!string.IsNullOrEmpty(fileName))
{
var resp = await Client.PutAsJsonAsync<ExceptionFileQuery, string>("", new ExceptionFileQuery() { FileName = fileName });
Assert.NotNull(resp);
}
}
}
}

View File

@ -1,7 +1,7 @@
using System.Net.Http;
using Xunit;
namespace Bootstrap.Admin
namespace Bootstrap.Admin.Api
{
public class LoginTest : IClassFixture<BAWebHost>
{

View File

@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Mvc.Testing;
using System.Net.Http;
using System.Threading.Tasks;
using UnitTest;
namespace Bootstrap.Admin
@ -16,5 +18,24 @@ namespace Bootstrap.Admin
// Copy license
TestHelper.CopyLicense();
}
public async Task<string> LoginAsync(HttpClient client)
{
var r = client.GetAsync("/Account/Login").GetAwaiter().GetResult();
var view = r.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var tokenTag = "<input name=\"__RequestVerificationToken\" type=\"hidden\" value=\"";
var index = view.IndexOf(tokenTag);
view = view.Substring(index + tokenTag.Length);
index = view.IndexOf("\" /></form>");
var antiToken = view.Substring(0, index);
var content = new MultipartFormDataContent();
content.Add(new StringContent("Admin"), "userName");
content.Add(new StringContent("123789"), "password");
content.Add(new StringContent("true"), "remember");
content.Add(new StringContent(antiToken), "__RequestVerificationToken");
var resp = client.PostAsync("/Account/Login", content).GetAwaiter().GetResult();
return await resp.Content.ReadAsStringAsync();
}
}
}

View File

@ -1,68 +0,0 @@
using System.Net.Http;
using Xunit;
namespace Bootstrap.Admin
{
public class AccountTest : IClassFixture<BAWebHost>
{
private HttpClient _client;
public AccountTest(BAWebHost factory)
{
_client = factory.CreateClient();
}
[Fact]
public async void Login_Fail()
{
// login
var r = await _client.GetAsync("/Account/Login");
Assert.True(r.IsSuccessStatusCode);
var content = await r.Content.ReadAsStringAsync();
Assert.Contains("登 陆", content);
}
[Fact]
public async void Login_Admin()
{
// login
var r = await _client.GetAsync("/Account/Login");
Assert.True(r.IsSuccessStatusCode);
var view = await r.Content.ReadAsStringAsync();
var tokenTag = "<input name=\"__RequestVerificationToken\" type=\"hidden\" value=\"";
var index = view.IndexOf(tokenTag);
view = view.Substring(index + tokenTag.Length);
index = view.IndexOf("\" /></form>");
var antiToken = view.Substring(0, index);
var content = new MultipartFormDataContent();
content.Add(new StringContent("Admin"), "userName");
content.Add(new StringContent("123789"), "password");
content.Add(new StringContent("true"), "remember");
content.Add(new StringContent(antiToken), "__RequestVerificationToken");
r = await _client.PostAsync("/Account/Login", content);
var resp = await r.Content.ReadAsStringAsync();
Assert.Contains("注销", resp);
}
[Fact]
public async void Logout_Ok()
{
// logout
var r = await _client.GetAsync("/Account/Logout");
Assert.True(r.IsSuccessStatusCode);
var content = await r.Content.ReadAsStringAsync();
Assert.Contains("登 陆", content);
}
[Fact]
public async void AccessDenied_Ok()
{
// logout
var r = await _client.GetAsync("/Account/AccessDenied");
Assert.True(r.IsSuccessStatusCode);
var content = await r.Content.ReadAsStringAsync();
Assert.Contains("您无权访问本页面请联系网站管理员授权后再查看", content);
}
}
}

View File

@ -0,0 +1,53 @@
using System.Net.Http;
using Xunit;
namespace Bootstrap.Admin.Controllers
{
public class AccountTest : ControllerTest
{
private BAWebHost _factory;
public AccountTest(BAWebHost factory) : base(factory, "Account", false)
{
_factory = factory;
}
[Fact]
public async void Login_Fail()
{
// login
var r = await Client.GetAsync("Login");
Assert.True(r.IsSuccessStatusCode);
var content = await r.Content.ReadAsStringAsync();
Assert.Contains("登 陆", content);
}
[Fact]
public async void Login_Admin()
{
// login
var resp = await _factory.LoginAsync(Client);
Assert.Contains("注销", resp);
}
[Fact]
public async void Logout_Ok()
{
// logout
var r = await Client.GetAsync("Logout");
Assert.True(r.IsSuccessStatusCode);
var content = await r.Content.ReadAsStringAsync();
Assert.Contains("登 陆", content);
}
[Fact]
public async void AccessDenied_Ok()
{
// logout
var r = await Client.GetAsync("AccessDenied");
Assert.True(r.IsSuccessStatusCode);
var content = await r.Content.ReadAsStringAsync();
Assert.Contains("您无权访问本页面请联系网站管理员授权后再查看", content);
}
}
}

View File

@ -0,0 +1,47 @@
using System.Net;
using System.Net.Http;
using Xunit;
namespace Bootstrap.Admin.Controllers
{
public class AdminTest : ControllerTest
{
public AdminTest(BAWebHost factory) : base(factory, "Admin", true)
{
}
[Theory]
[InlineData("Index", "欢迎使用后台管理")]
[InlineData("Users", "用户管理")]
[InlineData("Groups", "部门管理")]
[InlineData("Dicts", "字典表维护")]
[InlineData("Roles", "角色管理")]
[InlineData("Menus", "菜单管理")]
[InlineData("Logs", "系统日志")]
[InlineData("FAIcon", "图标集")]
[InlineData("IconView", "图标分类")]
[InlineData("Settings", "网站设置")]
[InlineData("Notifications", "通知管理")]
[InlineData("Profiles", "个人中心")]
[InlineData("Exceptions", "程序异常")]
[InlineData("Messages", "站内消息")]
[InlineData("Tasks", "任务管理")]
[InlineData("Mobile", "客户端测试")]
public async void View_Ok(string view, string text)
{
var r = await Client.GetAsync(view);
Assert.True(r.IsSuccessStatusCode);
var content = await r.Content.ReadAsStringAsync();
Assert.Contains(text, content);
}
[Fact]
public async void Error_Ok()
{
var r = await Client.GetAsync("Error");
Assert.False(r.IsSuccessStatusCode);
Assert.Equal(HttpStatusCode.InternalServerError, r.StatusCode);
}
}
}

View File

@ -0,0 +1,18 @@
using System.Net.Http;
using Xunit;
namespace Bootstrap.Admin.Controllers
{
public class ControllerTest : IClassFixture<BAWebHost>
{
protected HttpClient Client { get; }
public ControllerTest(BAWebHost factory, string controller, bool login)
{
factory.ClientOptions.BaseAddress = new System.Uri($"http://localhost/{controller}/");
Client = factory.CreateClient();
if (login) factory.LoginAsync(Client).GetAwaiter();
}
}
}

View File

@ -1,15 +1,14 @@
using System.Net.Http;
using Xunit;
namespace Bootstrap.Admin
namespace Bootstrap.Admin.Controllers
{
public class HomeTest : IClassFixture<BAWebHost>
public class HomeTest : ControllerTest
{
private HttpClient _client;
public HomeTest(BAWebHost factory)
public HomeTest(BAWebHost factory) : base(factory, "Home", true)
{
_client = factory.CreateClient();
}
[Theory]
@ -18,7 +17,7 @@ namespace Bootstrap.Admin
[InlineData(500)]
public async void Error_Ok(int errorCode)
{
var r = await _client.GetAsync($"/Home/Error/{errorCode}");
var r = await Client.GetAsync($"Error/{errorCode}");
Assert.True(r.IsSuccessStatusCode);
var content = await r.Content.ReadAsStringAsync();
if (errorCode == 0)

View File

@ -0,0 +1,42 @@
using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace Bootstrap.Admin
{
public static class HttpClientExtensions
{
public static async Task<T> GetAsJsonAsync<T>(this HttpClient client, string requestUri)
{
var resp = await client.GetAsync(requestUri);
var json = await resp.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(json);
}
public static async Task<TRet> PostAsJsonAsync<TValue, TRet>(this HttpClient client, string requestUri, TValue t)
{
var resp = await client.PostAsJsonAsync(requestUri, t);
var json = await resp.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TRet>(json);
}
public static async Task<TRet> DeleteAsJsonAsync<TValue, TRet>(this HttpClient client, string requestUri, TValue t)
{
var req = new HttpRequestMessage(HttpMethod.Delete, "");
req.Content = new StringContent(JsonConvert.SerializeObject(t));
req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var resp = await client.SendAsync(req);
var json = await resp.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TRet>(json);
}
public static async Task<TRet> PutAsJsonAsync<TValue, TRet>(this HttpClient client, string requestUri, TValue t)
{
var resp = await client.PutAsJsonAsync(requestUri, t);
var json = await resp.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TRet>(json);
}
}
}