Palmi
Palmi

Reputation: 2521

Setup Mock to redirect to overloaded method

I have a method called:

SendMail(string from, string to, string subject, string smtpServer)

and an overloaded Method

SendMail(string from, string to, string subject, SmtpClient smtpClient)

In my unit test I want to setup my MailService mock so that when the method SendMail(string, string, string, string) is called I want to instead call the overloaded method SendMail(string, string, string, SmtpClient) and modify the last parameter to a created SmtpClient test object.

Is there a way to do that?

Upvotes: 2

Views: 3024

Answers (2)

Michal Ciechan
Michal Ciechan

Reputation: 13898

What you want is to use .Callback(...) on your Setup

mailServiceMock
  .Setup(m => m.SendMail(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())
  .CallBack((string from, string to, string subject, string server) => mailService.SendMail(from, to, subject, server, SomeSMTPServer)

More importantly why are you trying to do this?

Normally you would only test that your mock got called with (string, stirng, string, string).

And then another TestClass/Fixture you would test that when you call the

(string from, string to, string subject, string smtpServer) 

overload, you actually call the SmtpServer overload with correct details.

EDIT: After comments

mailService is not a typo.

This will either be:

  1. The same mocked isntance (e.g. mailServiceMock.Object) if var mailServiceMock = new Mock<ParentClassNotInterface>{ CallsBase = true }. This would ofcourse mean your methods have to be virtual.
  2. An actual concrete implementation of the class/interface.

As to the second note, if I was you I would break this up into one/some/all of the following:

  • Unit test that the calling class/method calls SendServer(string, string, string, string). I would use the technique I describe on my blog: CodePerf[dot]NET - TDD – Mock.Throw Interface Call Verification Technique

  • Unit test that when you call SendServer(string, string, string, string) it calls SendServer(string, string, string, SmtpServer) with SmtpServer being set correctly.

  • Integration test that SendServer(string, string, string, SmtpServer)` actually sends the email.

  • Possibly an end-to-end test (no mocks) that this all works.

Upvotes: 5

garryp
garryp

Reputation: 5776

At its simplest

mailServiceMock.Setup(m => m.SendMail(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<SmtpClient>()));

With a callback/return bolted on if you want to.

Upvotes: 0

Related Questions