前置き
現場の案件で、外部APIやDB接続が絡んだ少々複雑な判定でCookie を作成するという処理を実装することになり、
対象の処理でユニットテストを作成しておきたくなりました。
Cookie の作成や、作成した値を検証するには当然ですがHttpRequestやHttpResponseのインスタンスが必要ですが、
これらのクラスのインスタンスをユニットテストで生成するのは困難(ほぼ不可能のはず)です。
そこで、ASP.NET ではHttpRequestWrapperというクラスが実装されています。
HttpRequestWrapperはHttpRequestBaseという抽象クラスから派生されています。
HttpRequestBaseはHttpRequestと同じプロパティ、関数を保有したクラスです。
対象となる処理の実装ではHttpRequestBaseを使用し、
HttpRequestWrapperでHttpRequestをラップしたインスタンスを使用することにします。
これらはHttpResponseでも同様です。
文章だとややこしいので、サンプルコードを実装してみました。
Controller(HttpRequestBase, HttpResponseBaseを使用する処理)
public class IndexController { public IndexController() { } public void createCookie(HttpRequestBase request, HttpResponseBase response) { if (request.QueryString == null) { throw new ArgumentNullException(); } string value = request.QueryString["hoge"]; var cookie = new HttpCookie("hoge"); cookie.Value = "hoge" + value; response.Cookies.Add(cookie); } }
aspx.cs
public partial class Index : System.Web.UI.Page { private readonly IndexController _controller = new IndexController(); protected void Page_Load(object sender, EventArgs e) { _controller.createCookie(new HttpRequestWrapper(Request), new HttpResponseWrapper(Response)); } }
そして、ユニットテストコードでは以下のようにHttpRequestBaseから派生したMockクラスを作成し、
テストで必要となるプロパティや関数をOverrideして実装します。
Mockクラス
public class HttpRequestMock : HttpRequestBase { private readonly NameValueCollection _queryString; public HttpRequestMock(NameValueCollection queryString) { _queryString = queryString; } public override NameValueCollection QueryString => _queryString; } public class HttpResponseMock : HttpResponseBase { private readonly HttpCookieCollection _cookies = new HttpCookieCollection(); public override HttpCookieCollection Cookies => _cookies; }
テストコード
[TestMethod]
public void createCookieNormalCase()
{
// Arrange
var requestMock = new HttpRequestMock(new NameValueCollection() { { "hoge", "12345" } });
var responseMock = new HttpResponseMock();
var sut = new IndexController();
// Act
sut.createCookie(requestMock, responseMock);
// Assert
Assert.AreEqual("hoge12345", responseMock.Cookies["hoge"].Value);
}
サンプルコード
今回の記事で作成したサンプルコードをGitHubにアップしました。