通过将抽象类实例化为模拟对象来对抽象类进行单元测试是否可以?

时间:2011-04-12 08:20:54

标签: c# unit-testing inheritance mocking abstract-class

我注意到你可以通过将抽象类实例化为一个模拟对象来对它进行单元测试。因此,您可以模拟抽象属性和方法,同时能够测试已实现的属性和方法。

但是,我习惯于将类测试和注入的依赖项区分为mock / stub 。那么,在我新启蒙的早期阶段,我想知道这种测试方法是否有任何陷阱?有什么想法吗?

此致 的Morten

5 个答案:

答案 0 :(得分:10)

具有任何值的抽象类应该具有可以实例化的具体子类。所以单元测试那些,并通过它们隐含地基类。

如果它没有具体的子类,我想不出它应该存在的任何理由(作为抽象类,即)。

一般来说,我更喜欢使用mocking来设置要测试的类的 environment ,而不是实例化类本身。这种区别 - 对我来说 - 使测试用例更加清晰,并确保我始终测试该类的实际功能。

当然,当主要问题是无论如何能够以某种方式编写单元测试以启用重构时,我可以想到案例(使用遗留代码)(如Working Effectively with Legacy Code中所述)。作为这种情况下的临时解决方案,(几乎)任何事情都会发生。但是一旦单元测试工作,该类应该适当地重构,以使其干净和可测试(并且它的单元测试也是如此,以使它们可维护)。

答案 1 :(得分:3)

不要使用继承来组合两个类,而是查看是否可以使用合成。

所以不要这样:

abstract class PaySalary {
    payAmount(decimal money) {
        if (transferAmount(money)) {
            isPaid = true;
        }
    }

    abstract void transferAmount(decimal money);
}

这样做:

class PaySalary {
    public MoneyTransferrer;

    payAmount(decimal money) {
        if (MoneyTransferrer.transferAmount(money)) {
            isPaid = true;
        }
    }
}

这样,您不必在单元测试中继承该类,但您只需模拟MoneyTransferrer即可。您还可以在不依赖基类的情况下测试MoneyTransferrer。

答案 2 :(得分:3)

如果我正在测试的部分中没有具体的实现,我通常会编写一个测试实现。在单元测试中,我做了类似我班级用户的事情。如果他继承了我的班级,我会在考试中继承。

另一方面,我不会说使用模拟框架来创建实现是不好的。在我的情况下,我通常不工作,通常是因为我需要为该类编写ORM映射文件以及类似的东西。

答案 3 :(得分:0)

根据定义,abstract class是抽象的。如果真的是抽象的话,应该没有什么可以测试的。

答案 4 :(得分:0)

是的,您将像测试注入接口一样测试抽象类。

如果您为ILog编写测试并使用MockLog注入测试以进行测试,那么您将对LogBase(在此示例中为抽象类)执行相同的操作并将其注入与MockLog相同。

abstract class不是interface,但是从开销来看,它们的用法几乎相同。