Search code examples
asp.net-mvc-3spark-view-engine

Add ViewFolder in config for Spark in ASP.NET MVC Unit Test project


I'm sending an email from my ASP.NET MVC app using the Spark View Engine based on this example by Andrew Kharlamov.

I've setup a unit test, CanSendEmail, but I need to specify the viewfolder in the config. I found the documentation here and the examples give this:

<spark>
  <views>
    <add name="{any-unique-name}" 
        folderType="FileSystem|EmbeddedResource|VirtualPathProvider|Custom"
        type="{name, assembly of IViewFolder type}"
        constuctor-param-names="values"
        subfolder="{optional subfolder to target}"/>
  </views>
</spark>

My question is this. Which folderType do I use and do I need any other parameters. My test product is call myProject.Tests and my web project containing the views is called myProject.Web with a Views folder in it.

Do I use FileSystem, VirtualPathProvider ... ?

Edit [14/11/2011]:

Okay I've got this in my app.config in myProject.Tests:

<views>
    <add name="web-view-folder"
                folderType="VirtualPathProvider"
                virtualBaseDir="~/Views"/>
</views>

I still get "View source file not found." when I run my test. I want the test to use the Views in myproject.Web.


Solution

  • My Solution

    Based on the blog posts here and here, and with help from @RobertTheGrey and looking at the tests in the Spark source code, I ended up using ViewFolderType.FileSystem. That worked.

    Here's the my code under test:

    public string RenderEmailWithCustomViewFolder(string sparkViewName, ViewDataDictionary viewData, Dictionary<string, string> viewFolderParameters)
    {
        var settings = new SparkSettings()
            .SetPageBaseType(typeof (SparkView))
            .AddViewFolder(ViewFolderType.FileSystem, viewFolderParameters)
            .AddAssembly("MvcContrib");
    
        var engine = new SparkViewEngine(settings);
    
    
        var sparkViewDescriptor = new SparkViewDescriptor().AddTemplate(sparkViewName);
        var view = (SparkView)engine.CreateInstance(sparkViewDescriptor);
        try
        {
            // Merge view data
            viewData.Keys.ToList().ForEach(x => view.ViewData[x] = viewData[x]);
    
            // Render the view to a text writer
            var writer = new StringWriter();
            view.RenderView(writer);
            return writer.ToString();
        }
        finally
        {
            engine.ReleaseInstance(view);
        }
    }
    

    And here's my test:

    [Test]
    public void Can_Render_Order_Confirmation_Email_With_Spark_View_Engine()
    {
        // Arrange
        var order = OrderInstanceFactory.CreateTestOrder();
        order.ContactEmail = "test@testicle.com";
        var emailService = new EmailService();
        var viewData = new ViewDataDictionary();
        viewData["Order"] = order;
        const string viewFolder = @"../../../../app/myProject.Web/Views";
        var viewFolderParameters = new Dictionary<string, string> {{"basePath", viewFolder}};
    
        // Act
        var emailBody = emailService.RenderEmailWithCustomViewFolder("Email/OrderConfirmation.spark", viewData, viewFolderParameters);
    
        // Assert
        Assert.IsNotNull(emailBody);
        Assert.IsTrue(emailBody.Contains("test@testicle.com"));
    }
    

    My OrderConfirmation.spark template lives in my web products in the Views/Email/.