我想知道如何单元测试抽象类,以及扩展抽象类的类。

我是否应该通过扩展抽象类来测试它,去掉抽象方法,然后测试所有的具体方法?然后只测试我重写的方法,并在单元测试中测试扩展抽象类的对象的抽象方法?

我是否应该有一个抽象测试用例,可以用来测试抽象类的方法,并在测试用例中为扩展抽象类的对象扩展该类?

注意,我的抽象类有一些具体的方法。


当前回答

如果您的抽象类包含具有业务价值的具体功能,那么我通常会通过创建一个测试双存根来直接测试它,或者使用一个模拟框架来为我做这件事。我选择哪一个很大程度上取决于我是否需要编写抽象方法的特定于测试的实现。

我需要这样做的最常见的场景是当我使用模板方法模式时,例如当我正在构建某种将由第三方使用的可扩展框架时。在本例中,抽象类定义了我想要测试的算法,因此测试抽象基类比测试特定实现更有意义。

然而,我认为重要的是这些测试应该只关注真实业务逻辑的具体实现;您不应该单元测试抽象类的实现细节,因为您最终会得到脆弱的测试。

其他回答

如果抽象类适合于您的实现,则测试(如上所述)派生的具体类。你的假设是正确的。

为了避免将来的混乱,请注意这个具体的测试类不是模拟的,而是假的。

严格来说,mock由以下特征定义:

A mock is used in place of each and every dependency of the subject class being tested. A mock is a pseudo-implementation of an interface (you may recall that as a general rule, dependencies should be declared as interfaces; testability is one primary reason for this) Behaviors of the mock's interface members -- whether methods or properties -- are supplied at test-time (again, by use of a mocking framework). This way, you avoid coupling of the implementation being tested with the implementation of its dependencies (which should all have their own discrete tests).

我为抽象类和接口所做的工作如下:我编写一个测试,将对象作为具体对象使用。但是在测试中没有设置类型为X的变量(X是抽象类)。这个测试类并没有添加到测试套件中,而是它的子类,它们有一个setup-方法,将变量设置为x的具体实现。这样我就不会重复测试代码。如果需要,未使用测试的子类可以添加更多的测试方法。

如果具体方法调用任何抽象方法,该策略将不起作用,您将希望分别测试每个子类的行为。否则,只要抽象类的具体方法与子类解耦,就可以像您所描述的那样扩展它并存根抽象方法。

如果您的抽象类包含具有业务价值的具体功能,那么我通常会通过创建一个测试双存根来直接测试它,或者使用一个模拟框架来为我做这件事。我选择哪一个很大程度上取决于我是否需要编写抽象方法的特定于测试的实现。

我需要这样做的最常见的场景是当我使用模板方法模式时,例如当我正在构建某种将由第三方使用的可扩展框架时。在本例中,抽象类定义了我想要测试的算法,因此测试抽象基类比测试特定实现更有意义。

然而,我认为重要的是这些测试应该只关注真实业务逻辑的具体实现;您不应该单元测试抽象类的实现细节,因为您最终会得到脆弱的测试。

为了专门对抽象类进行单元测试,您应该出于测试目的派生它,test base.method()的结果和继承时预期的行为。

你通过调用一个方法来测试它,所以通过实现一个抽象类来测试它……