續上篇,https://dotblogs.com.tw/yc421206/2016/08/02/identity_oauth_owin_setup
隨著功能的演進,原本用 Fiddler 編寫的測試腳本,越來越不容易管理,Web API 的品質也越來越不穩定
有了 TestServer 之後,我的問題就一掃而空,接下來就來分享我的作法,
開發環境
- Windows 10 Enterprise x64 CHT
- VS2015 Update3 ENG
目錄
- #Step1.在 Simple.OAuthServer.Test 測試專案安裝以下套件
- #Step2.使用 TestServer 建立 Web API
- #Step3.加入測試方法
- #結論
- #參考資源
- #專案連結
Step1.在 Simple.OAuthServer.Test 測試專案安裝以下套件
版本號會隨著時間不斷的更新,以下是我寫本篇時最新的版本
在 Simple.OAuthServer.Test 測試專案安裝以下套件
Install-Package Microsoft.Owin.Host.SystemWeb (3.0.1)
Dependencies
Owin (>= 1.0.0)
Microsoft.Owin (>= 3.0.1)
Install-Package Microsoft.AspNet.Identity.Owin (2.2.1)
Dependencies
Microsoft.AspNet.Identity.Core (>= 2.2.1)
Microsoft.Owin.Security (>= 2.1.0)
Microsoft.Owin.Security.Cookies (>= 2.1.0)
Microsoft.Owin.Security.OAuth (>= 2.1.0)
Install-Package Microsoft.Owin.Security.OAuth (3.0.1)
Dependencies
Owin (>= 1.0.0)
Microsoft.Owin (>= 3.0.1)
Newtonsoft.Json (>= 6.0.4)
Microsoft.Owin.Security (>= 3.0.1)
Install-Package Microsoft.AspNet.WebApi.Owin (5.2.3)
Dependencies
Microsoft.AspNet.WebApi.Core (>= 5.2.3 && < 5.3.0)
Microsoft.Owin (>= 2.0.2)
Owin (>= 1.0.0)
Install-Package Microsoft.Owin.Testing (3.0.1)
Dependencies
Owin (>= 1.0.0)
Microsoft.Owin.Hosting (>= 3.0.1)
Install-Package Microsoft.Owin.Diagnostics (3.0.1)
Dependencies
Owin (>= 1.0.0)
Microsoft.Owin (>= 3.0.1)
Step2.使用 TestServer 建立 Web API
首先,調用 TestServer.Create 搭建服務
[TestInitialize]
public void Setup()
{
Server = TestServer.Create(app =>
{
var startup = new Startup();
startup.Configuration(app);
app.UseErrorPage(); // See Microsoft.Owin.Diagnostics
app.UseWelcomePage("/Welcome"); // See Microsoft.Owin.Diagnostics
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
});
}
然後使用 TestServer.CreateRequest 發送命令
protected virtual async Task<HttpResponseMessage> PostAsync<TModel>(string uri, TModel model)
{
return await Server.CreateRequest(uri)
.And(
request =>
request.Content =
new ObjectContent(typeof(TModel), model, new JsonMediaTypeFormatter()))
.PostAsync();
}
protected virtual async Task<HttpResponseMessage> GetAsync(string uri)
{
return await Server.CreateRequest(uri)
.GetAsync();
}
最後將這些方法集結成抽象類別
public abstract class BaseServerTest
{
protected TestServer Server;
protected abstract string Password { get; set; }
protected abstract string Username { get; set; }
[TestInitialize]
public void Setup()
{
Server = TestServer.Create(app =>
{
var startup = new Startup();
startup.Configuration(app);
app.UseErrorPage(); // See Microsoft.Owin.Diagnostics
app.UseWelcomePage("/Welcome"); // See Microsoft.Owin.Diagnostics
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
});
}
[TestCleanup]
public void Teardown()
{
if (Server != null)
{
Server.Dispose();
}
}
protected virtual async Task<HttpResponseMessage> GetAsync(string uri)
{
return await Server.CreateRequest(uri)
.GetAsync();
}
protected virtual async Task<HttpResponseMessage> PostAsync<TModel>(string uri, TModel model)
{
return await Server.CreateRequest(uri)
.And(
request =>
request.Content =
new ObjectContent(typeof(TModel), model, new JsonMediaTypeFormatter()))
.PostAsync();
}
protected virtual async Task<HttpResponseMessage> GetAsync(string uri, string accessToken)
{
return await Server.CreateRequest(uri)
.AddHeader("Authorization", "Bearer " + accessToken)
.GetAsync();
}
protected virtual async Task<HttpResponseMessage> PostAsync<TModel>(string uri, TModel model, string accessToken)
{
return await Server.CreateRequest(uri)
.AddHeader("Authorization", "Bearer " + accessToken)
.And(
request =>
request.Content =
new ObjectContent(typeof(TModel), model, new JsonMediaTypeFormatter()))
.PostAsync();
}
}
建立一個實作 BaseServerTest 的 AccountApiControllerTest 類,測試方法調用 Web API
測試註冊帳號
[TestMethod]
public async Task Register_Test()
{
var model = new RegisterBindingModel
{
Email = Username,
Password = Password,
ConfirmPassword = Password
};
var response = await PostAsync(s_baseUri + "/Register", model);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
測試OAuth登入
[TestMethod]
public async Task Login_Bearer_Test()
{
var model = new RegisterBindingModel
{
Email = Username,
Password = Password,
ConfirmPassword = Password
};
await PostAsync(s_baseUri + "/Register", model);
var form = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", Username},
{"password", Password}
};
var content = new FormUrlEncodedContent(form);
var response =
Server.HttpClient.PostAsync("/oauth/token", content).Result;
var token = response.Content.ReadAsAsync<Token>(new[] {new JsonMediaTypeFormatter()}).Result;
response.StatusCode.Should().Be(HttpStatusCode.OK);
token.AccessToken.Should().NotBeNullOrEmpty();
}
結論
原本我也是使用 PostMan | Fiddler 測試 Web API,寫好的腳本,仍然可以納入版控,不過我一直有個問題,『自動測試』,我不知道如何運行自動測試
現在,在一行 Code 都不需要修改的情況之下,我引入了 TestServer,把原本使用 Fiddler 測試改用 TestServer + Unit Test 測試,大大的提升產品的穩定度,讓測試專案能在版控伺服器裡面被追蹤,也能讓 CI Server 運行自動測試
參考資源
https://blogs.msdn.microsoft.com/webdev/2013/11/26/unit-testing-owin-applications-using-testserver/
http://www.aaron-powell.com/posts/2014-01-12-integration-testing-katana-with-auth.html
專案連結
https://dotblogsamples.codeplex.com/SourceControl/latest#Simple.OAuthServer/
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET