Mocking base class and calling a non-virtual method

2,699 views
Skip to first unread message

CJM3407

unread,
Jun 30, 2011, 11:47:34 AM6/30/11
to Moq Discussions
I am not 100% sure how to word this, so I will just explain what I
want to do. I have a base class that has two methods, a virtual
method(PublishHourEnding) and a non-virtual method (PublishRecords).
The non-virtual method takes in a list of date times and loops through
each and sends it to the virtual method, which processes the
individual date time. I want to test the base class, so I can test
the behavior of the non-virtual method (it contains all the error
handling and reporting).

In my head, I want to be able to create a mock of my base class, and
call setup(x => x.PublishHourEnding(It.IsAny<DateTime>())).Throws(new
Exception("testing)). But I want to call PublishRecords with its
current behavior (don't want to change its behavior); I want to test
that all of this logic is working correctly.

Is this possible or not clear?

Tim Kellogg

unread,
Jun 30, 2011, 6:21:16 PM6/30/11
to moq...@googlegroups.com
Moq will override anything that is virtual. If you try to mock a non-virtual method Moq will throw an exception. If I understand you correctly, you want to mock the virtual methods, so this should work exactly as you want. 

If you want to test a virtual method you can set the `CallBase = true` on the mock. This will instruct the mock to call the method with it's regular functionality but allow you to still Verify it. Again, it is impossible to mock a non-virtual method/property (but that's the only kind that is impossible)

--Tim


Cameron Murdaugh

unread,
Jul 1, 2011, 9:39:17 AM7/1/11
to moq...@googlegroups.com
I guess is there a way to set moq to create a instance of a base class.  Like where I am defining a class that extends my base class.  I realize now looking at my base class, all of the method calls are abstract except for PublishGenerationRecords.  The abstract makes it where I can't do var actionBase = new Mock<PublishActionBase); actionBase.Setup(x => x.PublishHourEnding(**)).Returns(**);

Is there a flag that says I want to create a Mock of an object that extends PublishActionBase without creating a mock class first?

Tim Kellogg

unread,
Jul 1, 2011, 10:47:33 AM7/1/11
to moq...@googlegroups.com
If you want to create an instance of the base class, use the `new` operator. Moq generates a class that extends the base class and overrides all virtual members and gives an implementation to all abstract members. So you can perform setups & verify anything that is abstract or virtual.

I don't understand why you don't think you can do setups on abstract members. Is it because those abstract members are protected? If so, kzu has a great blog post about this: http://blogs.clariusconsulting.net/kzu/mocking-protected-members-with-moq/

--Tim

Cameron Murdaugh

unread,
Jul 1, 2011, 11:52:44 AM7/1/11
to moq...@googlegroups.com
I am not sure what I am doing incorrectly with this setup method.
var mockLogger = new Mock<ILogger>();

var container = new UnityContainer()
                .RegisterInstance(mockLogger.Object);

var action = new MockPublishAction(container, ((d1) => { throw new ServiceAgentException("CriticalReason", "CriticalService",           "CriticalOperation", true); }));

var mockAction = new Mock<PublishActionBase>(container);
mockAction.Protected().Setup<OperationReport>("PublishHourEnding", It.IsAny<DateTime>()).Returns((DateTime d) =>
                                                                                                                 {
                                                                                                                     throw
                                                                                                                         new ServiceAgentException
                                                                                                                             ("CriticalReason",
                                                                                                                              "CriticalService",
                                                                                                                              "CriticalOperation",
                                                                                                                              true);
                                                                                                                 });

var hourEndings = new List<DateTime>();
hourEndings.Add(new DateTime(2011, 1, 1, 1, 0, 0));
hourEndings.Add(new DateTime(2011, 1, 1, 2, 0, 0));
hourEndings.Add(new DateTime(2011, 1, 1, 3, 0, 0));

// action
var operationList = mockAction.Object.PublishGenerationRecords(hourEndings);
 
To help understand the code.  PublishGenerationRecords calls PublishHourEnding in a loop, and I want PublishHourEnding to immediately throw a ServiceAgentException, so that the try-catch in PublishGenerationRecords will catch it, and process it correctly(which is what I am testing).  I also tried using .Throws when setting up PublishHourEnding, but it has had the same issue.  The issue is the exception is not being thrown when calling PublishHourEnding.

Any help would be awesome.  Side question why is the Setup when using Protected() not the same syntax as the original setup (lambda argument).

Tim Kellogg

unread,
Jul 1, 2011, 4:21:53 PM7/1/11
to moq...@googlegroups.com
There's a subtle paragraph towards the end of kzu's blog mentioning that you need to use `ItExpr` instead of `It`. For some reason having to do with parsing expression trees he couldn't reuse `It` so he had to create `ItExpr` for protected members.

--Tim

Gmail

unread,
Jul 2, 2011, 1:49:15 PM7/2/11
to moq...@googlegroups.com
Awesome that works perfectly thanks. 

Thank you
Cameron Murdaugh
Reply all
Reply to author
Forward
0 new messages