But as we drill into that it begs a question, “What is the MockInsightManager?” As with many classes, the InsightManager does not have an interface and has some “non-overrideable” members that make Mocking hard. One trick I use when I encounter that is a wrapper with an interface. So let me show all these items, the IInsightManagerBase, InsightManagerWrapper, and MockInsightManager so you can get a sense for the overall layout:

IInsightManagerBase

publicinterfaceIInsightManagerBase

{

bool IsCaseSubmitted { get; }

CaseReport CreateCase();

void SubmitCase(CaseReport caseReport);

}

InsightManagerWrapper

publicclassInsightManagerWrapper : IInsightManagerBase

{

public InsightManagerWrapper()

{

Manager = InsightManager.Current;

}

privateInsightManager Manager { get; set; }

publicbool IsCaseSubmitted

{

get;

privateset;

}

publicException FailureException { get; set; }

publicCaseReport CreateCase()

{

return Manager.CreateCase();

}

publicvoid SubmitCase(CaseReport caseReport)

{

try

{

Manager.SubmitCase(caseReport);

IsCaseSubmitted = true;

}

catch (Exception ex)

{

FailureException = ex;

IsCaseSubmitted = false;

}

}

MockInsightManager

publicclassMockInsightManager : IInsightManagerBase

{

public MockInsightManager(bool submitCaseFails)

{

SubmitCaseFails = submitCaseFails;

}

publicbool SubmitCaseFails { get; set; }

publicbool IsCaseSubmitted { get; set; }

publicCaseReport CreateCase()

{

returnInsightManager.Current.CreateCase();

}

publicvoid SubmitCase(CaseReport caseReport)

{

if (!SubmitCaseFails)

{

IsCaseSubmitted = true;

}

}

}

So now we have a lot of the backup code, what does the actual view code in the controller look like? I’ll first show what it would look like if you just used the insight manager for those that want to see what it would look like when using Insight out of the box:

Feedback method out-of-box

[AcceptVerbs(HttpVerbs.Post)]

publicActionResult Feedback(CaseReportDetail detail)

{

try

{

var report = InsightManager.Current.CreateCase();

report.EmailAddress = detail.Email;

report.Title = detail.Title;

report.Description = detail.Description;

report.CaseType = CaseType.Inquiry;

InsightManager.Current.SubmitCase(report);

return View("FeedbackReceived", detail);

}

catch

{

ModelState.AddModelError("Feedback", "There was a problem submitting the feedback. You may try to press submit again to try again. We apologize for the inconvenience.");

return View();

}

}

With no real indirection above, now let’s look at the controller after I modified it for easier unit testing.

Here’s the top of the controller class where I have a constructor:

HelpController constructor

publicclassHelpController : Controller

{

privateIInsightManagerBase _insightManager { get; set; }

public HelpController()

: this(newInsightManagerWrapper())

{

}

public HelpController(IInsightManagerBase insightManager)

{

_insightManager = insightManager;

}

And here is the modified View method based on this new constructor:

Feedback

[AcceptVerbs(HttpVerbs.Post)]

publicActionResult Feedback(CaseReportDetail detail)

{

var report = _insightManager.CreateCase();

report.EmailAddress = detail.Email;

report.Title = detail.Title;

report.Description = detail.Description;

report.CaseType = CaseType.Inquiry;

_insightManager.SubmitCase(report);

if (_insightManager.IsCaseSubmitted)

{

return View("FeedbackReceived", detail);

}

else

{

ModelState.AddModelError("Feedback", "There was a problem submitting the feedback. You may try to press submit again to try again. We apologize for the inconvenience.");

return View();

}

}

The Negative Case

So now the original test works… but what happens if something goes wrong when submitting the case?

I added a new test that looks like this:

Feedback_Not_Received

[TestCategory("Build"), TestCategory("Unit"), TestMethod]

publicvoid Feedback_Not_Received()

{

// Arrange

string expected = "Feedback"; // Did not work so we stayed on the Feedback view showing the error.

Assert.IsFalse(result.ViewData.ModelState.IsValid); // Was the model invalid?

actual = result.ViewName;

Assert.AreEqual(expected, actual); // Did it forward to the right view?

}

Then when I was done, I had 100% code coverage for the Feedback method!

I hope this helps others unit test the CodeSmith Insight…

This entry was posted on Saturday, May 29th, 2010 at 5:37 pm and is filed under Technology. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.