Simple question from theoretical point of view. If i have Email
class with Send()
method inside which is responsible for sending email. Send()
method is declared in interface called IEmail
. Let's assume i will moq
that method as IEmail
interface in my unit test. Then when i Setup
moq with Send()
and later on use Verify()
method then i suppose real email will be not send but only check whether Send()
method was called properly. Am i right? Second to check real Send()
to really send email i should use integration test. Is that all correct?

- 27,588
- 3
- 45
- 62

- 19
- 3
-
`moq` generated methods will do nothing other than track that they've been called. – willaien Mar 05 '19 at 14:54
-
Yes, you are correct. – Fabio Mar 05 '19 at 19:48
1 Answers
Presumably what you're testing isn't the actual Email
class. If it's a concrete class that sends an email, then calling Send
will (and probably should) send an email.
Mocking would be useful for testing a class that depends on your IEmail
interface. It allows you to verify that your class does what is expected with the interface it depends on. In that case you wouldn't want to send an email. You just want to test that your class tells IEmail
to send an email.
Here's a contrived example of a class that depends on an IEmail
interface to send an email.
public class ClassThatSendsEmail
{
private readonly IEmail _email;
public ClassThatSendsEmail(IEmail email)
{
_email = email;
}
public void DoSomethingThatCausesAnEmailToGetSent()
{
var message = new Message {To = "bob@bob.com", Body = "Hi, Bob!"};
_email.Send(message);
}
}
...and here are some other types I threw together just for testing:
public interface IEmail
{
void Send(Message message);
}
public class Message
{
public string To { get; set; }
public string Body { get; set; }
}
Here's a very simple test that will mock IEmail
.
public class Tests
{
[TestCase]
public void MyClassSendsAnEmail()
{
var emailMock = new Mock<IEmail>();
emailMock.Setup(x=>x.Send(It.IsAny<Message>())).Verifiable();
var subject = new ClassThatSendsEmail(emailMock.Object);
subject.DoSomethingThatCausesAnEmailToGetSent();
emailMock.Verify(x=>x.Send(It.IsAny<Message>()));
}
}
To directly answer your question, no email will get sent because the concrete Email
class is nowhere in the picture. I haven't even created one. My class only depends on the interface, so I can test it before I've even written an implementation of IEmail
. The test is just going to verify that my class called the Send
method of the mock.
(This is a great way to prevent coupling. I don't want my class to be tightly coupled to some other class that sends emails, so that the one class only works with the other. If the first class works as expected when I haven't even created the second class then it's not coupled to the second class.)
Sometimes it's convenient to write a test double, which is an actual class that implements the interface just for test purposes. You can do this same stuff with Moq, but sometimes all the setup code gets complicated and using a test double just makes it easier to read.
So here's a test double for IEmail
. When you send a message it's going to add the message to a list. That way after the test is run you can look at what's in the list to see if the correct email got sent:
public class EmailListDouble : List<Message>, IEmail
{
public void Send(Message message)
{
Add(message);
}
}
Now you can easily write a test which verifies that IEmail.Send
was called and that the expected message was sent:
[TestCase]
public void MyClassSendsAnEmail()
{
var email = new EmailListDouble();
var subject = new ClassThatSendsEmail(email);
subject.DoSomethingThatCausesAnEmailToGetSent();
Assert.True(email.Any(message=> message.To == "bob@bob.com" && message.Body.Contains("Bob")));
}
Moq is great, but sometimes the setup can not only become a little cumbersome, but it also makes it harder to tell what's getting tested. Sometimes just using a test double gets the job done and it's easier.

- 27,588
- 3
- 45
- 62
-
and how integration test could look like, could you post some example based on that? P.S In your second test the real email will be send because i do not see moq? And is it more like integration test then? – abc Mar 05 '19 at 16:38
-
I googled and found this, which I never knew about: https://stackoverflow.com/questions/3998436/how-to-test-sending-emails-from-asp-net-on-development-machine. Assuming that you're using an SMTP client, you could configure it to "send" emails to a folder, and then you could read them and inspect them. I've never integration tested actual emails, though. If I'm using the framework classes then there doesn't seem to be a need. That would seem more like testing the infrastructure. But I guess there's a case for everything. – Scott Hannen Mar 05 '19 at 16:43