首页 > 解决方案 > 在 C# 测试中使用 Moq 覆盖 System.Configuration 值

问题描述

我的任务是向一些预先存在的代码添加测试。我们试图将重构保持在最低限度,因此这些测试通常是单元/集成测试的组合。

我们也在这个项目中使用 Moq,我正在快速学习。

我的问题是,如何使用 Moq 来覆盖下面 SendEmail 中的 System.Configuration 值(EmailFrom、EmailTo 等),这样我就不必在我们所有的测试 System.Configuration 文件中不断地照看 System.Configuration 值? 我只是想测试我们执行 Email.send 代码

    public clas EmailLogging
    {
       public void SendEmail(string error}
            {
               string EmailFrom = System.Configuration.ConfigurationSettings.AppSettings["EmailFrom"].ToString();
               string EmailTo = System.Configuration.ConfigurationSettings.AppSettings["EmailTo"].ToString();
               string errorLogLocation = System.Configuration.ConfigurationSettings.AppSettings["ErrorLogLocation"].ToString();
               ...
               using (SmtpClient client = new SmtpClient())
                {
                   client.Send(mailMessage);
                }

标签: c#automated-testsmoq

解决方案


如何使用 Moq 覆盖 System.Configuration 值

起订量没有能力

覆盖 System.Configuration 值

选项1

在测试项目的app.config中设置值,因为这将是运行测试的上下文。

优点:无需重构代码。

缺点:必须在我们所有的测试 System.Configuration 文件中不断地照看 System.Configuration 值。

选项 2

将代码重构为更加可靠,而不是依赖于实现问题

public interface IConfigurationSettings {
    string AppSettings[string key] { get; }
}

public interface ISmtpClient: IDisposable {
    void Send(Message message);
}

public interface IEmailLogging  {
    void SendEmail(string error);
}

public class EmailLogging: IEmailLogging {
    private readonly IConfigurationSettings ConfigurationSettings;
    private readonly ISmtpClient client;

    public EmailLogging (IConfigurationSettings settings,  ISmtpClient client) {
        this.ConfigurationSettings = settings;
        this.client = client;
    }

    public void SendEmail(string error) {
       string EmailFrom = ConfigurationSettings.AppSettings["EmailFrom"];
       string EmailTo = ConfigurationSettings.AppSettings["EmailTo"];
       string errorLogLocation = ConfigurationSettings.AppSettings["ErrorLogLocation"];

       //...

       client.Send(mailMessage);            
    }
}

这将允许关注点分离,也允许单独测试单独的实现,而不会产生连锁反应。

依赖的类EmailLogging现在可以依赖于它的抽象,并在测试时根据需要替换它以确认它SendEmail被调用。


推荐阅读