如何根据头文件中定义的代码测试类?

时间:2013-05-16 17:07:11

标签: c++ unit-testing

我正在开始使用C ++进行单元测试,而我正试图找出最佳实践。然而今天,我在编写使用boost interprocess的代码时遇到了一些障碍,特别是在头文件中定义的file_mapping和mapped_region。

我的一般问题是:如何根据头文件中定义的代码(即Boost和STL)测试类?

实施例: 假设我创建了一个这样的类 MyClass.h:

#pragma once

#include <stddef>

namespace boost { namespace interprocess {
class mapped_region;
}}

class MyClass
{
public:
    MyClass(mapped_region& mapped_region);
    std::size_t get_size() const;

private:
    boost::interprocess::mapped_region& mapped_region_;
}

MyClass.cpp文件:

#include "MyClass.h"
#include <boost/interprocess/mapped_region.hpp>

using namespace boost::interprocess;

MyClass::MyClass(mapped_region& mapped_region)
: mapped_region_(mapped_region) {}

std::size_t MyClass::get_size() const
{
    return mapped_region_.get_size();
}

如何测试MyClass :: get_size()?由于mapped_region仅在头文件中实现,因此它将创建一个基本上独立于其他目标文件的对象文件(也就是说,不需要链接),因此创建伪造或模拟对象不会因为它无法链接。

我能看到工作的唯一方法是在.cpp中使用#ifdefs并在MyClass.cpp中执行类似的操作:

#ifdef RUN_UNITTEST
#include "my_fake_mapped_region.h"
#else
#include <boost/interprocess/mapped_region.hpp>
#endif

但这看起来像是一个可怕的黑客攻击并通过测试感染生产代码。

我想可以在测试代码中使用boost,但这需要在磁盘上创建文件,技术上不再是单元测试,而是集成测试? (对不起,如果我对术语有误)。

我真的很感激这个问题的一些见解。

1 个答案:

答案 0 :(得分:2)

创建典型抽象层的方法是将违规库包装在一个非常薄的层后面,然后将其注入需要它的对象的构造函数中。你已经明白,包装每一个boost函数都会使用boost来使用一个困难的非标准混乱的包装器。

正如您所发现的那样,您不能简单地从库继承接口,因为声明包含实现,因为它是给您带来问题的实现。

诀窍是认识到你不必包装每个增强模板。你只需要包装那些给你“难以设置”和“难以测试”的问题。 <{1}}有资格成为难以测试的问题之一,所以它值得包装。

请记住,您不应该尝试在这里测试提升。您的单元测试不会(也不应该)关心它是否设置了真实的内存映射或调用假的内存映射,只要该调用似乎有效,因此您的测试可以继续进行。您也不需要测试您创建的包装器,只要它们太薄以至于您可以轻松验证它们不包含逻辑。例如,我不打算测试boost::interprocess方法,因为视觉检查显示它只返回返回的值。