I'm a sitecore developer and I want to create a sample sitecore helix unit testing project for testing out the logic you see in our "EmailArticleController" controller's Index() action method:
using Sitecore.Mvc.Presentation;
public class EmailArticleController : GlassController
{
//logic in below Index() method is what I want to test
public override ActionResult Index()
{
var _emailArticleBusiness = new EmailArticleBusiness();
var model = _emailArticleBusiness.FetchPopulatedModel;
var datasourceId = RenderingContext.Current.Rendering.DataSource;
_emailArticleBusiness.SetDataSourceID(datasourceId);
return View("~/Views/EmailCampaign/EmailArticle.cshtml", model);
}
//below is alternative code I wrote for mocking and unit testing the logic in above Index() function
private readonly IEmailArticleBusiness _businessLogic;
private readonly RenderingContext _renderingContext;
public EmailArticleController(IEmailArticleBusiness businessLogic, RenderingContext renderingContext)
{
_businessLogic = businessLogic;
_renderingContext = renderingContext;
}
public ActionResult Index(int forUnitTesting)
{
var model = _businessLogic.FetchPopulatedModel;
// *** do below two lines of logic somehow go into my Unit Testing class? How?
var datasourceId = _renderingContext.Rendering.DataSource;
_businessLogic.SetDataSourceID(datasourceId);
// ***
return View("~/Views/EmailCampaign/EmailArticle.cshtml", model);
}
}
OK this is what I have in my unit testing class:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Test_EmailArticleController_With_RenderingContext()
{
//Arrange
var businessLogicFake = new Mock<IEmailArticleBusiness>();
var model = new EmailArticleViewModel()
{
ArticleControl = new Article_Control() { },
Metadata = new Metadata() { }
};
businessLogicFake.Setup(x => x.FetchPopulatedModel).Returns(model);
// I'm not sure about the next 3 lines, how do I mock the RenderingContext and send it into the constructor, given that it needs a DataSource value too?
var renderingContext = Mock.Of<Sitecore.Mvc.Presentation.RenderingContext>( /*what goes here, if anything?*/ ) { /*what goes here, if anything?*/ };
EmailArticleController controllerUnderTest = new EmailArticleController(businessLogicFake.Object, renderingContext);
var result = controllerUnderTest.Index(3) as ViewResult;
Assert.IsNotNull(result);
}
}
Basically I want to mock a rendering context, make sure it has a (string) DataSource value set to some value such as "/sitecore/home/...", I want to send it into the controller's constructor (if that's the proper way), call the Index(int ) method, and at the same time make sure my _businessLogic, which is only an interface in this case (should it be the concrete class instead?) has its dataSource set to that same value before returning the View.
What's the exact code for doing all of this? Thanks!
Tightly coupling your code to static dependencies like
RenderingContext.Current.Rendering.DataSource
can make testing your code in isolation difficult.I would suggest you create a wrapper to encapsulate the static access to the
RenderingContext
. Referring to code examples found at the Glass.Mapper repository on GitHubYou would then update your controller to explicitly depend on that abstraction via constructor injection
You are now able to mock all dependencies to be able to test the controller in isolation.
Your production code would obviously register the abstraction and implementation with your DI container for runtime resolution of dependencies.