views:

54

answers:

3

I want to test that the "Create" method on the _eventManager in my controller gets called. When I run my test, I get the following exception:

Test method Baigent.TheDoNation.Application.Tests.EventControllerTest.Create_Post_IfModelIsValidRedirectToSuccessfullyCreatedViewOccurs threw exception: System.ArgumentException: Invalid setup on a non-overridable member: m => m.CreateEvent(It.IsAny(), It.IsAny()).

The code for the controller is:

    public ActionResult Create(Event eventObject, FormCollection collection)
    {
        if (ModelState.IsValid)
        {
            _eventManager.CreateEvent(eventObject, User.Identity.Name);

            return RedirectToAction("SuccessfullyCreated", new { });
        }

        // Invalid - redisplay form with errors
        return View(GetEventViewModel(eventObject));
    }

The _eventManager field gets set in the constructor. My test is :

        var eventManagerMock = new Mock<EventManager>(new FakeEventsRepository());
        eventManagerMock.Setup(m => m.CreateEvent(It.IsAny<Event>(), It.IsAny<String>())).Verifiable("No call to CreateEvent on the EventManager was made");

        var eventController = new EventController(eventManagerMock.Object);

        var newEvent = new Event {Name = "Test Event", Date = DateTime.Now, Description = "Test description"};

        // Act
        var result = eventController.Create(newEvent, new FormCollection()) as RedirectToRouteResult;

        // Assert
        eventManagerMock.Verify(m => m.CreateEvent(It.IsAny<Event>(), It.IsAny<String>())); 

        Assert.IsNotNull(result, "RedirectToRouteResult should be returned");
        Assert.AreEqual("SuccessfullyCreated", result.RouteValues["action"], "Redirect should be to SuccessfullyCreated view");

Please help!

A: 

Moq can only mock virtual members of your EventManager type. You should consider extracting a IEventManager interface, or make the CreateEvent method virtual.

Romain Verdier
Thank you, you are right. I actually came to this conclusion 10 minutes after posting - a post in haste methinks.
A: 

You will either have to make the method Virtual or you will need to define an interface that has the method CreateEvent() and then Mock the interface :]

You now want to mock a Method in which Moq has no direct rights to override it.

Bas
+1  A: 

The exception tells you that you are trying to override a non-virtual member, which is impossible.

Moq (as well as Rhino Mocks and NMock) can only override virtual members (including pure interface members).

See here for a more detailed explanation.

Mark Seemann