RazorEngine to support @Html / @Url methods

I recently used the latest RazorEngine library to build unit tests for views.  However I didn’t get any sample code doing exactly what I wanted to do.  When I ran the simple view test, I got the following error:

RazorEngine.Templating.TemplateCompilationException: Unable to compile template. You can find the generated source code in .
– error: (28, 13) The name ‘Html’ does not exist in the current context

The reason is because by default RazorEngine didn’t support any html helper methods, such as Html.Raw.  You needed to do your own implementation and register through TemplateServiceConfiguration.  Below are a sample code to provide Html.Raw method when parsing the view.

using System.IO;
using System.Web.Mvc;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RazorEngine;
using RazorEngine.Configuration;
using RazorEngine.Templating;

namespace OneStore.UnitTests.Views
{
    [TestClass]
    [DeploymentItem(@"Views\Test\index.cshtml", @"Views\Test\")]
    public class FaqPageTests
    {
        private static string viewTemplate;

        [ClassInitialize]
        public static void SetupView(TestContext context)
        {
            // You can get view template as below; remember to set DeploymentItem with correct path and set the view's "Copy to output directory" to "Copy if newer".
            viewTemplate = File.ReadAllText(@"Views\Test\index.cshtml");

            // 2 approaches to implement view test using RazorEngine library.
            // And there are 2 different syntax to construct the template service.
            // you can pick which approach and syntax you prefer.

            // Personally, I prefer "using (var service = ...)" syntax instead of assigning service to static instance property.
            // For appraoch, I prefer "FakeHtmlHelper" which controls exactly what the method should behave.
        }

        [TestMethod]
        public void TestOption1()
        {
            // Arrange
            string htmlMarkup = string.Empty;
            string template = "<div>Hello @Html.Raw(Model.Name)</div>";

            var config = new TemplateServiceConfiguration
            {
                BaseTemplateType = typeof(MyCustomTemplateBase1<>)
            };

            // Act
            using (var service = new TemplateService(config))
            {
                htmlMarkup = service.Parse(template, new { Name = "TestName" }, null, null);
            }

            // Assert
            htmlMarkup.Should().NotBeNullOrEmpty();
        }

        [TestMethod]
        public void TestOption2()
        {
            // Arrange
            string htmlMarkup = string.Empty;
            string template = "<div>Hello @Html.Raw(Model.Name)</div>";

            var config = new TemplateServiceConfiguration
            {
                BaseTemplateType = typeof(MyCustomTemplateBase1<>)
            };
            var service = new TemplateService(config);
            Razor.SetTemplateService(service);

            // Act
            htmlMarkup = service.Parse(template, new { Name = "TestName" }, null, null);

            // Assert
            htmlMarkup.Should().NotBeNullOrEmpty();
        }
    }

    public abstract class MyCustomTemplateBase1<T> : TemplateBase<T>
    {
        public readonly HtmlHelper<T> Html = new HtmlHelper<T>(new ViewContext(), new FakeViewDataContainer());
    }

    public class FakeViewDataContainer : IViewDataContainer
    {
        private ViewDataDictionary _viewData = new ViewDataDictionary();
        public ViewDataDictionary ViewData { get { return _viewData; } set { _viewData = value; } }
    }

    public abstract class MyCustomTemplateBase2<T> : TemplateBase<T>
    {
        public readonly FakeHtmlHelper<T> Html = new FakeHtmlHelper<T>();
    }

    public class FakeHtmlHelper<T>
    {
        public string Raw(string value)
        {
            return string.Format("[Html.Raw: {0}]", value);
        }
    }
}

Hope this sample code will help you to build your unit tests using RazorEngine.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s