C# - 单元测试视图模型的 public getter 而不调用 class 构造函数?
C# - Unit test view model's public getter without calling class constructor?
如何在不调用 class 的构造函数的情况下从单元测试调用 C# 属性 的 public getter?
我目前正在为视图模型编写单元测试。
我没有测试私有方法,只测试 public 方法。
我正在测试任何实现自定义逻辑或验证的 public getters 和 setter。
我的 class 包含一个私人项目列表。
我的 class 包含一个 属性,其中 returns 其中一些项目基于项目的 属性 值。
我的 class 包含一个调用数据库的构造函数。
我想测试 getter returns 那些项目是否正确,因为 getter 是 class 的 public 界面的一部分,并且应该测试一下。
我的问题是我想以某种方式模拟我的 class,以便我可以在单元测试期间调用 class 属性 的 getter。但是,我不想调用 class 的构造函数,因为这意味着调用数据库并执行测试预期范围之外的其他工作。
这是一个猴子和香蕉的例子:
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
属性 测试 getter。
我不想调用构造函数,因为我不想调用 GetBananasFromDatabase()
方法。
PeeledBananas
getter 是 monkey
class 的 public API 的一部分,因此应该对其进行单元测试。但是测试的时候应该不会调用数据库。
我可以创建一个新的 monkey
模拟,无论如何我都可以调用构造函数并模拟 GetBananasFromDatabase()
方法的行为,但我不能模拟 GetBananasFromDatabase()
方法因为它是私人的。
解决这个问题的好方法是什么?
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
可以从任何 database
对给定上下文有意义的东西中得到 bananas
,并且 monkey
class 不再紧密耦合特定的 IDatabase
实现。
当我想在生产代码中使用 monkey
class 时,我用一些 RealDatabase
实例化了 class。当我想对 monkey
class 进行单元测试时,我用一些 FakeDatabase
实例化了 class。两者都实现了 IDatabase
和 GetBananas()
,因此 monkey
无论如何都有效。
谢谢你的提示,Nkosi!
如何在不调用 class 的构造函数的情况下从单元测试调用 C# 属性 的 public getter?
我目前正在为视图模型编写单元测试。
我没有测试私有方法,只测试 public 方法。
我正在测试任何实现自定义逻辑或验证的 public getters 和 setter。
我的 class 包含一个私人项目列表。
我的 class 包含一个 属性,其中 returns 其中一些项目基于项目的 属性 值。
我的 class 包含一个调用数据库的构造函数。
我想测试 getter returns 那些项目是否正确,因为 getter 是 class 的 public 界面的一部分,并且应该测试一下。
我的问题是我想以某种方式模拟我的 class,以便我可以在单元测试期间调用 class 属性 的 getter。但是,我不想调用 class 的构造函数,因为这意味着调用数据库并执行测试预期范围之外的其他工作。
这是一个猴子和香蕉的例子:
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
属性 测试 getter。
我不想调用构造函数,因为我不想调用 GetBananasFromDatabase()
方法。
PeeledBananas
getter 是 monkey
class 的 public API 的一部分,因此应该对其进行单元测试。但是测试的时候应该不会调用数据库。
我可以创建一个新的 monkey
模拟,无论如何我都可以调用构造函数并模拟 GetBananasFromDatabase()
方法的行为,但我不能模拟 GetBananasFromDatabase()
方法因为它是私人的。
解决这个问题的好方法是什么?
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
可以从任何 database
对给定上下文有意义的东西中得到 bananas
,并且 monkey
class 不再紧密耦合特定的 IDatabase
实现。
当我想在生产代码中使用 monkey
class 时,我用一些 RealDatabase
实例化了 class。当我想对 monkey
class 进行单元测试时,我用一些 FakeDatabase
实例化了 class。两者都实现了 IDatabase
和 GetBananas()
,因此 monkey
无论如何都有效。
谢谢你的提示,Nkosi!