shimapapa.io

.NET,VB,C#,AzureなどMS関連中心の技術ブログ

【C# / ASP.NET WebForm】HttpRequestBase を継承しMock クラスを作成し、HttpRequest をテストする

前置き

現場の案件で、外部APIやDB接続が絡んだ少々複雑な判定でCookie を作成するという処理を実装することになり、
対象の処理でユニットテストを作成しておきたくなりました。

Cookie の作成や、作成した値を検証するには当然ですがHttpRequestHttpResponseインスタンスが必要ですが、
これらのクラスのインスタンスユニットテストで生成するのは困難(ほぼ不可能のはず)です。

そこで、ASP.NET ではHttpRequestWrapperというクラスが実装されています。
HttpRequestWrapperHttpRequestBaseという抽象クラスから派生されています。
HttpRequestBaseHttpRequestと同じプロパティ、関数を保有したクラスです。
対象となる処理の実装ではHttpRequestBaseを使用し、
HttpRequestWrapperHttpRequestをラップしたインスタンスを使用することにします。
これらは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にアップしました。

github.com