gpt4 book ai didi

c# - 如何使单例设计可测试?

转载 作者:行者123 更新时间:2023-11-30 17:02:00 24 4
gpt4 key购买 nike

假设我有以下单例:

public class ConfigReader
{
static readonly ConfigReader instance = new ConfigReader();

private ConfigReader() { }

public static ConfigReader Instance { get { return instance; } }

public int RecordsPerPage
{
get
{
var configPath = DB.Table<ConfigSource>().GetFieldValue("Path").ToString();
if (configSource == "Database")
return Convert.ToInt32(DB.Table<Configuration>().GetFieldValue("RecordsPerPage"));
else
return Convert.ToInt32(ConfigurationManager.AppSettings["RecordsPerPage"]);
}
}
}

如何编写单元测试来模拟此单例中的 DB.Table 和 ConfigurationManager.AppSettings 调用,以便我可以使用单元测试对其进行测试?

其实这引出了TDD的另一个问题:我们在设计系统的时候真的有必要考虑可测试性吗?似乎不是每个设计都能符合 TDD 原则,比如 DI 等。我是不是误解了什么?

最佳答案

在设计系统的时候要不要考虑可测试性?如果您编写的代码符合 SOLID原则,那么你的系统将是可测试的。因此,只需考虑您是否需要良好的面向对象设计。

替代解决方案 - 如果您正在使用依赖注入(inject)框架,那么您可以只专注于此类的单一职责 - 读取配置值。第二个职责(保持类的单个实例)将交给 DI 框架,您将能够在这里使用简单的构造函数注入(inject)。

测试你的单例类 - 为了模拟类依赖,你应该依赖抽象而不是实现。并且您应该通过依赖注入(inject)提供实现。这里有几个选项 - 您可以将 RecordsPerPage 属性转换为方法并使用参数注入(inject):

public int RecordsPerPage(IConfigSource source)
{
var configPath = source.GetFieldValue("Path").ToString();
if (configPath == "Database")
return Convert.ToInt32(source.GetFieldValue("RecordsPerPage"));

return Convert.ToInt32(ConfigurationManager.AppSettings["RecordsPerPage"]);
}

现在您将能够将 IConfigSource 的 mock 传递给您的单例(Moq 示例):

int expected = random.Next();
Mock<IConfigSource> sourceMock = new Mock<IConfigSource>();
sourceMock.Setup(s => s.GetFieldValue("Path")).Returns("Database");
sourceMock.Setup(s => s.GetFieldValue("RecordsPerPage")).Returns(expected);

var reader = ConfigReader.Instance;
var actual = reader.RecordsPerPage(sourceMock.Object);

Assert.That(actual, Is.EqualTo(expected));
sourceMock.VerifyAll();

如果你想对单例的不同调用重用IConfigSource,那么你可以声明属性来设置它(属性注入(inject)):

public IConfigSource Source { get; set; }

并在测试期间设置源代码:

var reader = ConfigReader.Instance;
reader.Source = sourceMock.Object;
var actual = reader.RecordsPerPage;

关于c# - 如何使单例设计可测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20425833/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com