当前位置: 首页 > 知识库问答 >
问题:

C#-单元测试视图模型的公共getter,而不调用类构造函数?

柴浩大
2023-03-14

如何从单元测试中调用C#属性的公共getter,而不调用类的构造函数

我目前正在为视图模型编写单元测试。

我不是在测试私有方法,只是测试公共方法<我正在测试任何实现自定义逻辑或验证的公共getter和setter。

我的类包含一个私有项目列表<我的类包含一个属性,该属性根据项目的属性值返回其中一些项目<我的类包含一个调用数据库的构造函数。

我想测试这个getter是否正确返回这些项,因为getter是类公共html" target="_blank">接口的一部分,应该进行测试。

我的问题是,我想以某种方式模拟我的类,以便在单元测试期间调用类属性的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();
    }
}

在本例中,我想测试getter的peeledbananes属性
我不想调用构造函数,因为我不想调用GetBananasFromDatabase()方法。

PeeledBananers是monkey类的公共API的一部分,因此应该对其进行单元测试。但在测试期间不应调用数据库。

我可以创建一个新的猴子模拟,无论如何我都可以调用构造函数并模拟GetBananasFromDatabase()方法的行为,但我不能模拟GetBananasFromDatabase()方法,因为它是私有的。

解决这个问题的好方法是什么?

共有1个答案

莫典
2023-03-14

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();
    }
}

现在我的猴子可以从任何对给定上下文有意义的数据库中获取香蕉,并且猴子类不再紧密耦合到特定的IDatabase实现。

当我想在生产代码中使用猴子类时,我用一些RealDatabase实例化该类。当我想单元测试猴子类时,我用一些FakeDatabase实例化该类。两者都实现了IDatabaseGetBananas(),所以猴子无论如何都可以工作。

谢谢你的提示,恩科西!

 类似资料:
  • 问题内容: 如果我有一个像这样的抽象类: 还有一些从Item派生的类是这样的: 我不明白为什么我不能使用泛型调用构造函数: 我知道可以有一个没有构造函数的类型,但是这种情况是不可能的,因为Pencil具有没有参数的构造函数,而Item是抽象的。但是我从eclipse中得到了这个错误: 无法实例化 我不明白为什么的 T类型 ,以及如何避免这种情况? 问题答案: 无法使用Java类型系统来强制类层次结

  • 问题内容: 我有一个用JUnit4语法编写的测试类,可以使用“以junit测试方式运行”选项在eclipse中运行而不会失败。通过蚂蚁目标运行相同的测试时,出现以下错误: 我在类中没有public no arg构造函数,但这真的有必要吗? 这是我的蚂蚁目标 测试类没有构造函数,但是它具有带有默认修饰符的内部类。它也有一个匿名内部类。两个内部类均给出“ Test类应具有公共零参数构造函数错误”。我正

  • 问题内容: 我有一堂课要添加单元测试。该类具有多个构造函数,这些构造函数采用不同的类型并将其转换为规范形式,然后可以将其转换为其他类型。 实际上,它接受并转换为其他两种类型。 我正在尝试找出最合适的方法来测试这些构造函数。 应该有一个针对每个构造函数的测试和输出类型: 这导致许多不同的测试。如您所见,我正在努力命名它们。 应该有多个断言: 这有多个断言,这使我感到不舒服。它还正在测试getStri

  • 我试图从Spock测试中扩展GebSpec的类调用java构造函数。我有这样一个错误:“不允许构造函数;相反,定义一个'setup()'或'setup spec()'方法”。我需要打这样的电话:

  • 问题内容: 我在Sonar上收到此警告,我希望解决方案在声纳上消除此警告。我的课是这样的: 我想要适当的解决方案以消除此声纳警告。 问题答案: 如果此类仅是实用程序类,则应将该类定型并定义一个私有构造函数: 这样可以防止默认的无参数构造函数在代码的其他地方使用。另外,您可以将类定型,这样就不能在子类中对其进行扩展,这是实用程序类的最佳实践。由于您仅声明了一个私有构造函数,因此其他类将无法对其进行扩

  • 例如,我有一个这样的课; 我要做的是为模拟的构造函数编写单元测试。 如果是静态的,那么这将很容易,因为我可以使用然后调用构造函数。 有人知道有什么办法吗?