5

MVC 3 Preview 1 で新しい Razor ビュー エンジンを試しており、NUnit/Moq を使用して簡単な単体テストを書きたいと思っています。これが実際に行われている例はまだ見たことがありません - それは Razor の真のセールス機能の 1 つですが.

したがって、DBConext オブジェクト (最初に EF4 CTP コード) を使用するコントローラーがあり、コントローラーで呼び出されるアクションで読み込まれたモデルで提供されるアイテムのリストに基づいて、ビューがドロップダウン リストをレンダリングする場合、私は要素にアイテムが取り込まれていることをテストできるようにしたいと考えています。

これが私のコントローラーです:

public class WeatherReportController : Controller, IWeatherReportController
{
    private IWeatherDb _weatherDb;

    public WeatherReportController()
    {
        this._weatherDb = new WeatherDb();
    }

    public ActionResult Index()
    {
        WeatherReportIndexModel model = new WeatherReportIndexModel
        {
            Report = new WeatherReport {
                Username = this.HttpContext.User.Identity.Name,
                WeatherType = new WeatherType()
            },
            WeatherTypeList = _weatherDb.GetAllWeatherTypes()
        };
        return View(model);
    }

}

ここに私のモデルがあります:

public class WeatherReportIndexModel
{
    private IList<WeatherType> _weatherTypeList = new List<WeatherType>();
    public IList<WeatherType> WeatherTypeList { 
        get 
        {
            return _weatherTypeList;
        }
        set 
        {
            _weatherTypeList = value;
        }
    }

    [DisplayName("Type of Weather")]
    public IList<SelectListItem> WeatherTypeSelectItemList
    {
        get
        {
            int id = this.Report.WeatherType == null ? 0 : this.Report.WeatherType.WeatherTypeId;
            List<SelectListItem> selectListItems = this.WeatherTypeList.Select(weatherType => new SelectListItem
                                                                                   {
                                                                                       Value = weatherType.WeatherTypeId.ToString(),
                                                                                       Text = weatherType.Name,
                                                                                       Selected = weatherType.WeatherTypeId == id
                                                                                   }).ToList();
            selectListItems.Insert(0, new SelectListItem { Selected = (this.Report.WeatherType == null), Text = "Select Type of Weather", Value = "0" });
            return selectListItems;
        }
    }

    public WeatherReport Report { get; set; }
}

そして、ここに私の見解があります:

@inherits System.Web.Mvc.WebViewPage<Web.UI.Models.WeatherReportIndexModel>

@{
    View.Title = "Index";
    LayoutPage = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>


@using (Html.BeginForm()) {
    <div>
        <fieldset>
            <legend>New Weather Report</legend>
            <div class="editor-label">
                @Html.LabelFor(m => m.Report.WeatherType.WeatherTypeId)
                @Html.DropDownListFor(m => m.Report.WeatherType.WeatherTypeId, Model.WeatherTypeSelectItemList)
    <input type="submit" value="Log On" />
            </div>
  </fieldset>
 </div>
 }

私がこれまでに持っているテストコードは次のとおりです。

[TestFixture]
public class WeatherReportViewTests
{
    [Test]
    public void Can_render_weather_report_index_view_correctly()
    {

        var mockControllerContext = new Mock<ControllerContext>();
        var mockSession = new Mock<HttpSessionStateBase>();

        mockControllerContext.Setup(p => p.HttpContext.Request.HttpMethod).Returns("POST");
        mockControllerContext.Setup(p => p.HttpContext.Request.UserHostAddress).Returns("1.1.1.1");
        mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);
        mockControllerContext.Setup(p => p.HttpContext.Request.LogonUserIdentity).Returns(WindowsIdentity.GetCurrent());

        var routeData = new RouteData();
        routeData.Values.Add("controller", "WeatherReport");
        routeData.Values.Add("action", "Index");

        var viewEngine = new CshtmlViewEngine();
        var view = viewEngine.FindView(mockControllerContext.Object, "Index", "_Layout", false);
        var viewReponse = view.ToString();

        Assert.That(viewReponse, Contains.Substring("Sunny Intervals"));
    }
}

テストを実行すると、NullReferenceException が発生します。

アイデア/ポインタなどは大歓迎です。将来的に自分のビューでTDDを実行できるように、これを機能させたいと思っています。

前もって感謝します!

4

2 に答える 2

2

CshtmlViewEngine クラスを完全に避けて、Razor エンジンを自分で起動することをお勧めします。ASPX 以外での Razor ビューのコンパイルに関するブログ記事をここに書きました: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet.html

MVC3 のプレビュー 1 では、Razor エンジンは System.Web.Mvc 内に埋め込まれており、パブリック (IIRC) であるため、その投稿/サンプルで参照されているすべてのクラスを System.Web.Mvc.dll で見つけることができるはずです。

ページをコンパイルしたら、生成されたクラスをロードし、モック アウトされたコンテキスト オブジェクトを渡し、Execute() を呼び出します。ページの CodeDOM ツリーがあるため (Razor エンジンを使用する場合)、System.Web.Mvc.WebViewPage の代わりに、テスト ページの基本クラスから継承するように基本クラスを微調整することもできます。置換コンテキスト オブジェクトなどでスワップします。

于 2010-08-14T15:41:26.517 に答える
0

Razor ビューの単体テストについて書きました。それは醜く、あらゆる種類の厄介なものですが、機能し、すべてのプロジェクトですべてのビューをテストするために適応させることができました.

http://httputility.com/articles/unit-testing-razor-views.html

ただし、長期にわたるプロジェクトの場合は、MVC チームによって作成されたテスト ハーネスを待つことをお勧めします。

于 2011-03-08T22:18:46.767 に答える