8

I cannot successfully run unit tests for MvcMailer using the visual studio test suite and Moq. I have copied the example from the wiki word for word but get the following exception every time:

Test method MvcMailerTest.Tests.MailerTest.TestMethod1 threw exception: 
System.ArgumentNullException: Value cannot be null.
Parameter name: httpContext

Code is as follows: (Using the VS unit test framework - exact same error when using nUnit as in the example)

        //Arrange: Moq out the PopulateBody method
        var _userMailerMock = new Mock<UserMailer>();
        _userMailerMock.Setup(mailer => mailer.PopulateBody(It.IsAny<MailMessage>(), "Welcome", null));            
        _userMailerMock.CallBase = true;

        //Act
        var mailMessage = _userMailerMock.Object.Welcome();

Fails on the following line in the Welcome() method (copied straight out of the wiki):

 PopulateBody(mailMessage, viewName: "Welcome");

The wiki is here: https://github.com/smsohan/MvcMailer/wiki/MvcMailer-Step-by-Step-Guide

Similar (almost exactly the same) Question: MvcMailer: Can't complete NUnit tests on Razor Views which use Url.Action

Anyone know how to fix/get around this? The linked question says I need to mock out the PopulateBody method which I have done (as per wiki).

Community
  • 1
  • 1
woggles
  • 7,444
  • 12
  • 70
  • 130
  • This [issue was reported](https://github.com/smsohan/MvcMailer/issues/20) to the MVC Mailer team but was closed without a resolution. Does anyone have a workaround/fix? – jhappoldt Aug 25 '11 at 18:26
  • @Josh, unfortunately I still haven't found a fix or workaround. Guess this bug is in the hands of the MVC mailer devs... – woggles Aug 25 '11 at 19:10
  • 2
    a workaround is to change your code to this: `PopulateBody(mailMessage, "Welcome", null);` This will work because you have a mock setup for that overload of PopulateBody and not for the 2 parameter version of it.. – Filip Cornelissen Feb 28 '12 at 09:50
  • @FilipCornelissen: finally a solution that worked! Thanks mate... :) – Leniel Maccaferri Apr 21 '12 at 20:42
  • @FilipCornelissen dont you want to post your comment as an answer so that I can accept it? – woggles Apr 22 '12 at 12:01
  • done, now it can help the rest of the world ;-) – Filip Cornelissen Apr 22 '12 at 21:47

4 Answers4

3

A quick addition to Filip's answer that somebody might find helpful: I am using version 4.0 of the MvcMailer package. I was using the Populate(Action<MvcMailMessage> action) method inside my mailer actions and noticed that it uses a four-parameter version of PopulateBody:

// Mvc.Mailer.MailerBase (using ILSpy)
public virtual MvcMailMessage Populate(Action<MvcMailMessage> action)
{
    MvcMailMessage mvcMailMessage = new MvcMailMessage();
    action(mvcMailMessage);

    // Four parameters! (comment added by me)
    this.PopulateBody(mvcMailMessage, mvcMailMessage.ViewName, mvcMailMessage.MasterName, mvcMailMessage.LinkedResources);

    return mvcMailMessage;
}

As such, I found that setting up the mock with four parameters...

PopulateBody(mailMessage, "Welcome", "SomeMasterName", null);

...did the trick.

sammy34
  • 5,312
  • 5
  • 29
  • 42
2

a workaround is to change your code to this:

PopulateBody(mailMessage, "Welcome", null);

This will work because you have a mock setup for that overload of PopulateBody and not for the 2 parameter version of it..

Filip Cornelissen
  • 3,682
  • 3
  • 31
  • 41
0

You probably need to mock HttpContext too. You can do this by creating a HttpContextBase mock object and assign it to your Controller object.

Hadi Eskandari
  • 25,575
  • 8
  • 51
  • 65
  • I'm just trying to test the mailer for now, not the controller that uses the mailer (if that makes any difference!). – woggles May 21 '11 at 12:08
0

I suspect it is due to that you are reassigning a new mock to the _userMailerMock variable and therefore not actually mocking the PopulateBody method.

var _userMailerMock = new Mock<UserMailer>();
_userMailerMock.Setup(mailer => mailer.PopulateBody(It.IsAny<MailMessage>(), "Welcome", null));
_userMailerMock.CallBase = true;

Take out the second assignment _userMailerMock = new Mock<UserMailer>(); the line before Callbase = true;

aqwert
  • 10,559
  • 2
  • 41
  • 61
  • Oops I pasted the code into stackoverflow incorrectly. There is only 1 assigment to _userMailerMock in the code. Still get the same error. – woggles May 22 '11 at 10:51