如何在不调用类的构造函数的情况下从单元测试中调用C#属性的公共获取器?
我目前正在为视图模型编写单元测试。
我不是在测试私有方法,而只是在测试公共方法。
我正在测试实现自定义逻辑或验证的所有公共获取器和设置器。
我的课程包含一个私人的项目列表。
我的课程包含一个属性,该属性根据项目的属性值返回其中一些项目。
我的课程包含一个构造函数,该构造函数调用数据库。
我想测试此getter是否正确返回了这些项目,因为getter是该类的公共接口的一部分,应该对其进行测试。
我的问题是我想以某种方式模拟我的类,以便可以在单元测试期间调用class属性的getter。但是,我不想调用该类的构造函数,因为那将意味着调用数据库并在测试的预期范围之外执行其他工作。
这是猴子和香蕉的例子:
public class Monkey {
private List<Banana> bananas;
public Monkey()
{
this.GetBananasFromDatabase()
}
public List<Banana> PeeledBananas {
get {
List<Banana> peeledBananas = new List<Banana>();
foreach(Banana banana in this.bananas)
{
if(banana.IsPeeled)
{
peeledBananas.Add(banana);
}
}
return peeledBananas;
}
}
private GetBananasFromDatabase()
{
this.bananas = Database.GetBananas();
}
}
在此示例中,我要测试PeeledBananas
属性的吸气剂。
我不想调用构造函数,因为我不想调用GetBananasFromDatabase()
方法。
PeeledBananas
获取器是monkey
类的公共API的一部分,因此应该对其进行单元测试。但是在测试过程中不应调用数据库。
我可以创建一个新的monkey
模拟,无论如何我都可以调用构造函数,并且仅模拟GetBananasFromDatabase()
方法的行为,但是我不能模拟GetBananasFromDatabase()
方法,因为它是私人的。
什么是解决此问题的好方法?
答案 0 :(得分:1)
Nkosi的评论提供了有用的见解。我的问题是由于使用了具体的数据库类型,我的代码紧密耦合在一起。通过练习多态和控制反转(IOC),我决定将数据库接口传递给构造函数并在其上调用方法,而不是在具体数据库上调用方法。
现在,当我想对某项进行单元测试时,我可以将伪造的数据库对象传递到monkey
构造函数中,而不必触摸GetBananasFromDatabase()
方法。
代码如下所示:
public class Monkey {
private List<Banana> bananas;
private IDatabase database;
public Monkey(IDatabase database)
{
this.database = database;
this.GetBananasFromDatabase()
}
public List<Banana> PeeledBananas {
get {
List<Banana> peeledBananas = new List<Banana>();
foreach(Banana banana in this.bananas)
{
if(banana.IsPeeled)
{
peeledBananas.Add(banana);
}
}
return peeledBananas;
}
}
private GetInfoFromDatabase()
{
this.bananas = this.database.GetBananas();
}
}
现在,我的monkey
可以从bananas
中获得database
来获取给定上下文,monkey
类不再与特定的{{1 }}实施。
当我想在生产代码中使用IDatabase
类时,我用一些monkey
实例化该类。当我想对RealDatabase
类进行单元测试时,我用一些monkey
实例化该类。两者都实现FakeDatabase
和IDatabase
,因此GetBananas()
无论如何都可以工作。
感谢小费,恩科西!