18

I want to use it to fake System.Net.Mail.SmtpClient in a MS-Test UnitTest. Therefor I added a Fakes Assembmly of System.dll. Then I create a ShimsContext and a StubSmtpClient.

using (ShimsContext.Create())
{
   StubSmtpClient client = new StubSmtpClient();               
}

But what do I do with it? The ultimate goal would be to write a Test which expects that the send Method is called with a object of MailMessage.

4

4 回答 4

35

您可以创建一个接口,该接口将公开将从 SmtpClient 使用的功能

public interface ISmtpClient   
    {
        void Send(MailMessage mailMessage);
    }

然后创建你的具体类,它将做真正的工作。

 public class SmtpClientWrapper : ISmtpClient
    {
        public SmtpClient SmtpClient { get; set; }
        public SmtpClientWrapper(string host, int port)
        {
            SmtpClient = new SmtpClient(host, port);
        }
        public void Send(MailMessage mailMessage)
        {
            SmtpClient.Send(mailMessage);
        }
    }

现在,在您的测试方法中,您可以模拟它并使用 like;

[TestMethod()]
        public void SendTest()
        {
            Mock<ISmtpClient> smtpClient = new Mock<ISmtpClient>();
            SmtpProvider smtpProvider = new SmtpProvider(smtpClient.Object);
            string @from = "from@from.com";
            string to = "to@to.com";
            bool send = smtpProvider.Send(@from, to);
            Assert.IsTrue(send);
        }
于 2015-04-27T21:10:31.120 回答
8

这并不是您问题的真正答案,而是另一种方法:

在 app.config 中,设置 smtp 设置以将邮件作为文件传递到本地目录。然后您可以加载文件并检查您的断言部分中的内容。

您必须为断言编写更多代码(或者最好创建一些辅助函数),但您不必做任何影响生产代码的事情。

于 2013-11-14T06:52:32.590 回答
6

另一种选择是使用nDumbster

Install-Package nDumbster

它在内存中运行一个 SMTP 服务器,然后您可以对其进行验证。它把它变成了一个集成测试,但通常这些比单元测试具有更高的价值,因为你想要测试的SmtpClient用法也是正确的。

于 2015-08-06T19:36:14.823 回答
1

Teoman shipahi的这个答案的一个版本,它正确处理了.SmtpClient

首先使ISmtpClient继承IDisposable

public interface ISmtpClient : IDisposable
{
    void Send(MailMessage mailMessage);
}

然后IDisposableSmtpClientWrapper类中实现:

public class SmtpClientWrapper : ISmtpClient
{
    private bool disposed;
    private readonly SmtpClient smtpClient;

    public SmtpClientWrapper(string host, int port)
    {
        smtpClient = new SmtpClient(host, port);
    }

    ~SmtpClientWrapper()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                smtpClient?.Dispose();
            }
            disposed = true;
        }
    }

    protected void CheckDisposed()
    {
        if (disposed)
        {
            throw new ObjectDisposedException(nameof(SmtpClientWrapper));
        }
    }

    public void Send(MailMessage mailMessage)
    {
        CheckDisposed();
        smtpClient.Send(mailMessage);
    }
}

对于这个版本SmtpClientWrapper,我已经删除了该SmtpClient属性,以避免在属性SmtpClient的 setter 中替换时对象没有被处理的问题SmtpClient

于 2018-04-06T17:52:20.617 回答