c++ - 模拟系统调用 - 有更好的方法吗?

标签 c++ unit-testing mocking

<分区>

我们现在正在公司中引入单元测试,并考虑模拟系统调用的最佳方式。

考虑以下代码

    int fd = open(path, O_RDONLY);
    if (fd < 0) {
        LOG.error() << "cannot load plugin " << path << std::endl;
        return ERROR(ERROR_OPENING_PLUGING);
    }
    // do other stuff

显然,我们需要模拟系统调用以打开

我找到了以下方法:

  1. 正确 - 就设计而言,但方式很丑。创建接口(interface)并实现

    class ISystem
    {
    public:
        typedef std::auto_ptr<ISystem> Ptr;
    
        ISystem() {};
        virtual ~ISystem() {};
    
        virtual int open(const char* file, int path) = 0;
    };
    
    class System : public ISystem
    {
    public:
        System() {};
        virtual ~System() {};
    
        virtual int open(const char* file, int path);
    
        static ISystem::Ptr Get();
    };
    

并使用它

    Common::Error dlopen_signed(ISystem::Ptr& system, const char* path, int flags, void*& ret)
    {
    int fd = system->open(path, O_RDONLY);
    if (fd < 0) {
        LOG.error() << "cannot load plugin " << path << std::endl;
        return ERROR(ERROR_OPENING_PLUGING);
    }
    char fd_path[32];

我不喜欢它,因为每个函数都需要多一个参数 - ISystem::Ptr& system,这对于所有生产代码都是相同的。

此外,不确定速度(这涉及必须非常快的基本系统调用的额外层)

2) 使用链接接缝 链接器的设计使其更喜欢您的函数版本而不是系统版本。

但这对某些系统调用不起作用,例如open(不确定原因),并且这个解决方案有点hackish。

3) 使用 --wrap 编译器功能

--换行符 对符号使用包装函数。任何 undefined symbol 引用都将解析为 __wrap_symbol。对 __real_symbol 的任何 undefined reference 都将解析为符号。这可用于为系统功能提供包装器。包装函数应称为 __wrap_symbol。如果要调用系统函数,应该调用__real_symbol。这是一个简单的例子:

void *
__wrap_malloc (int c)
{
  printf ("malloc called with %ld\n", c);
  return __real_malloc (c);
} 

这个解决方案很好,但我猜并不适用于所有编译器。

问题是 - 您在项目中使用哪一个?

最佳答案

您必须对要模拟的内容和要进行单元测试的内容划清界线。 100% 的单元测试覆盖率并不是最终目标。

如果您真的想模拟系统调用,最好将它们放在包装器中(问题中的第一个选项)。不是一个巨大的包装器,但您应该按功能将它们分成几个包装器。

关于c++ - 模拟系统调用 - 有更好的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19785174/

相关文章:

python - Python 中的 with..as 子句断言

使用两个模拟对象进行 Python 单元测试,如何验证调用顺序?

C++ 数组 : Go from 1D to 2D

java - 如何捕获可变参数

c++ - 使用递归生成斐波那契数列的静态 vector 用法

java - 如何模拟实现类?

.net - 如何模拟类的内部方法?

unit-testing - 不明白 Spock 中的交互是如何运作的

c++ - Ifstream 因未知原因失败

c++ - 如何使用附加模板参数编写 not "in situ"方法