我之前用另一个名字问了这个问题,但删除了它,因为我没有很好地解释它.
假设我有一个管理文件的类.假设此类将文件视为具有特定文件格式,并包含对此文件执行操作的方法:
class Foo { std::wstring fileName_; public: Foo(const std::wstring& fileName) : fileName_(fileName) { //Construct a Foo here. }; int getChecksum() { //Open the file and read some part of it //Long method to figure out what checksum it is. //Return the checksum. } };
假设我希望能够对计算校验和的这个类的部分进行单元测试.单元测试加载到文件中的类的部分是不切实际的,因为要测试getChecksum()方法的每个部分,我可能需要构造40或50个文件!
现在假设我想在类中的其他地方重用校验和方法.我提取方法,使它现在看起来像这样:
class Foo { std::wstring fileName_; static int calculateChecksum(const std::vector<unsigned char> &fileBytes) { //Long method to figure out what checksum it is. } public: Foo(const std::wstring& fileName) : fileName_(fileName) { //Construct a Foo here. }; int getChecksum() { //Open the file and read some part of it return calculateChecksum( something ); } void modifyThisFileSomehow() { //Perform modification int newChecksum = calculateChecksum( something ); //Apply the newChecksum to the file } };
现在我想对calculateChecksum()方法进行单元测试,因为它很容易测试和复杂,而且我不关心单元测试getChecksum(),因为它很简单且很难测试.但我不能直接测试calculateChecksum(),因为它是私有的.
有谁知道这个问题的解决方案?
解决方法
基本上,听起来你想要一个
mock使单元测试更可行.您可以通过
dependency injection独立于对象层次结构和外部依赖关系来创建可用于单元测试的类的方法是通过
dependency injection创建一个类“FooFileReader”,如下所示:
class FooFileReader { public: virtual std::ostream& GetFileStream() = 0; };
制作两个实现,一个打开一个文件并将其公开为流(或者如果你真正需要的那样是一个字节数组.)另一个是一个模拟对象,只返回旨在强调你的算法的测试数据.
现在,让foo构造函数具有此签名:
Foo(FooFileReader* pReader)
现在,您可以通过传递模拟对象来构造用于单元测试的foo,或者使用打开文件的实现使用真实文件构造它.在factory中包含“真正的”Foo的构造,使客户端更容易获得正确的实现.
通过使用这种方法,没有理由不对“int getChecksum()”进行测试,因为它的实现现在将使用模拟对象.