【问题标题】:How to avoid base called method in xunit.net thanks to Mock感谢 Mock,如何避免 xunit.net 中的基调用方法
【发布时间】:2019-10-23 10:15:08
【问题描述】:

我正在尝试为我的 CutomSmtpMailer 编写单元测试代码。我的 CutomSmtpMailer 继承自 SmtpClient。

这是我的班级的样子:

public class CutomSmtpMailer : SmtpClient
{
    private void SendMail(MailMessage mailMessage)
    {
        //DoSomeStuff
        Send(mailMessage); //base.Send(mailMessage)
    }
}

我想在不发送邮件的情况下测试我的自定义代码:我想通过将其替换为空操作来避免调用“Send(mailMessage)”,但不知道它是否已被调用 .当我使用 DI 时,我知道如何模拟实例,但我不想注入 SMTPclient(事实上,我这里有很多继承的情况是一个简单的例子)

public class TestCutomSmtpMailer
{
    public CutomSmtpMailer Get()
    {
        return new CutomSmtpMailer();
    }

    [Fact]
    public void SendMail()
    {
        CutomSmtpMailer service = Get();
        MailMessage mailMessage = new MailMessage();
        // Find on web but not available :(
        Mock.Arrange(() => new SmtpClient().Send()).Returns(null).IgnoreInstance();
        service.SendMail(mailMessage);
    }
}

如何用空函数替换/模拟Parent类方法以避免发送邮件?

提前致谢

【问题讨论】:

  • 你不能。这就是为什么人们会注入SmtpClient
  • 这感觉就像XY problem。您选择继承 SmtpClient 的任何特殊原因?
  • 另外,昨天以duplicate 关闭,您将整个内容复制并粘贴到一个新问题中。不建议这样做。让我们看看我们是否可以充分改变这个问题以揭示实际问题并避免重复
  • 赞成您的问题,因为它非常清楚您想要做什么以及想要避免什么(依赖注入)。对我来说,这看起来不像是重复的,这与与the first question重复链接的情况截然不同。

标签: c# unit-testing inheritance parent-child xunit.net


【解决方案1】:

由于您不想使用 依赖注入 来注入 SmtpClient,因此您可以采取丑陋的方式并添加一个 internal 构造函数并委托给 CustomSmtpMailer帮助模拟和测试。 请注意,这种方法不是很干净。 这将导致代码纯粹用于在您的产品组装中进行测试,这通常不是一个好主意。

然而,它确实解决了您所描述的问题,让您不必使用依赖注入

public class CustomSmtpMailer : SmtpClient {

    internal delegate void SendInternal(MailMessage message);

    private SendInternal _sendAction;

    // make sure all your constructors call this one.
    // this will make the call to base.Send(MailMessage) the default behaviour.
    public CustomSmtpMailer() {
        _sendAction = delegate (MailMessage message) { Send(message); };
    }

    // customizes the SendMail(MailMessage) behaviour for testing purposes.
    internal CustomSmtpMailer(SendInternal sendAction) {
        _sendAction = sendAction;
    }

    private void SendMail(MailMessage mailMessage) {
        //DoSomeStuff

        _sendAction(mailMessage);
    }

}

通过将其添加到您项目中的AssemblyInfo.cs,使内部成员对您的测试项目可见。

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("My.Test.Assembly.Name")]

在您的单元测试中,您可以使用内部构造函数来配置基调用。

[Fact]
public void SendMail() {

    CustomSmtpMailer service = new CustomSmtpMailer(delegate (MailMessage message) {
        Console.WriteLine("I'm a custom Action that can be used for testing");
    });
    MailMessage mailMessage = new MailMessage();
    // Find on web but not available :(
    Mock.Arrange(() => new SmtpClient().Send()).Returns(null).IgnoreInstance();
    service.SendMail(mailMessage);

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-21
    • 2010-11-12
    • 1970-01-01
    • 2019-10-02
    • 1970-01-01
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多