如何在c+中模拟fork和execlp系统调用+;使用gmock框架进行单元测试? 我有现有的C++代码,它使用Frk()系统调用创建子进程。子进程使用execlp()系统调用执行linux命令。现在,我想使用gmock框架测试这段代码,代码覆盖率为100%。我在谷歌上搜索了很多,但没有得到任何完整的证明。有人能帮我吗

如何在c+中模拟fork和execlp系统调用+;使用gmock框架进行单元测试? 我有现有的C++代码,它使用Frk()系统调用创建子进程。子进程使用execlp()系统调用执行linux命令。现在,我想使用gmock框架测试这段代码,代码覆盖率为100%。我在谷歌上搜索了很多,但没有得到任何完整的证明。有人能帮我吗,c++,unit-testing,fork,gmock,execl,C++,Unit Testing,Fork,Gmock,Execl,这是我的SUT: int someclass :: os_fork() { pid_t pid = fork(); if (pid == -1) { cout<<"fork() failed with errno" <<errno <<endl; return false; } if (pid == 0 && (execlp("ls", "ls", nullptr) != 0)) { cout<<"

这是我的SUT:

int someclass :: os_fork()
{
  pid_t pid = fork();
  if (pid == -1) {
  cout<<"fork() failed with errno" <<errno <<endl;
  return false;
  }

  if (pid == 0 && (execlp("ls", "ls", nullptr) != 0))
  {
  cout<<"child process failed with errno"<<errno<<endl;
  return false;
  }
  int ppid = pid;
  return 0;
}
intsomeclass::os_fork()
{
pid_t pid=fork();
如果(pid==-1){

cout不可能模拟全局函数。相反,您可以添加一层抽象并将系统调用包装到接口中:

class OsInterface {
    virtual pid_t fork() = 0;
}

class OsInterfaceImpl : public OsInterface {
    virtual pid_t fork() override 
    {
        return ::fork();
    }
}

class OsInterfaceMock : public OsInterface {
    MOCK_METHOD0(fork, pid_t());
}
这允许您选择真正的系统调用或模拟。由于您没有提供任何代码,我无法帮助您

通常,您会将一个指向注入类的指针或引用传递给应该使用它的类的构造函数,但很少有其他方法更适合您的项目

另外一个优点是,这段代码更加开放和封闭:您可以轻松地(嗯,相对容易地)例如,在不更改现有代码的情况下添加Windows实现-您只需提供从
OsInterface
继承的另一个类即可。您不必更改生产代码中对接口的任何调用,只需更改注入的类即可


请注意,这将不会在单元测试中运行任何其他进程,但这是一个优势。您应该单独测试在进程中运行的代码。

不可能模拟全局函数。相反,您可以在接口中添加抽象层并包装系统调用:

class OsInterface {
    virtual pid_t fork() = 0;
}

class OsInterfaceImpl : public OsInterface {
    virtual pid_t fork() override 
    {
        return ::fork();
    }
}

class OsInterfaceMock : public OsInterface {
    MOCK_METHOD0(fork, pid_t());
}
这允许您选择真正的系统调用或模拟。由于您没有提供任何代码,我无法帮助您

通常,您会将一个指向注入类的指针或引用传递给应该使用它的类的构造函数,但很少有其他方法更适合您的项目

另外一个优点是,这段代码更加开放和封闭:您可以轻松地(嗯,相对容易地)例如,在不更改现有代码的情况下添加Windows实现-您只需提供从
OsInterface
继承的另一个类即可。您不必更改生产代码中对接口的任何调用,只需更改注入的类即可


请注意,这不会在单元测试中运行任何额外的进程,但这是一个优势。您应该单独测试在进程中运行的代码。

有点晚了,但您可以重新定义它,然后“注入”MockFunction以实现一些期望。我想是某种挂钩

#define CALL_ORIGINAL -2    
testing::MockFunction<int()> forkHelp;

pid_t fork(void)
{
    auto mockResult = forkHelp.Call();
    if (CALL_ORIGINAL != mockResult)
    {
        return mockResult;
    }
    return syscall(SYS_fork); /* Hack for calling real syscall */
}
#定义原始调用-2
测试::MockFunction forkHelp;
pid_t fork(无效)
{
auto mockResult=forkHelp.Call();
if(调用_ORIGINAL!=mockResult)
{
返回模拟结果;
}
return syscall(SYS_fork);/*用于调用实际syscall的Hack*/
}

顺便说一句,这种方法有它的缺点。测试结束时,它会说你的代码已经过时了),所以这取决于你来解决这个问题。

虽然有点晚了,但你可以重新定义它,然后“注入”MockFunction来实现一些期望。我想是某种挂钩

#define CALL_ORIGINAL -2    
testing::MockFunction<int()> forkHelp;

pid_t fork(void)
{
    auto mockResult = forkHelp.Call();
    if (CALL_ORIGINAL != mockResult)
    {
        return mockResult;
    }
    return syscall(SYS_fork); /* Hack for calling real syscall */
}
#定义原始调用-2
测试::MockFunction forkHelp;
pid_t fork(无效)
{
auto mockResult=forkHelp.Call();
if(调用_ORIGINAL!=mockResult)
{
返回模拟结果;
}
return syscall(SYS_fork);/*用于调用实际syscall的Hack*/
}

另外,这种方法有它的缺点。在测试结束时,它会说你的代码会消失),所以这取决于你来解决这个问题。

谢谢@Yksisarvinen的回复。我尝试过这种方法,但不起作用。你能解释一下如何在实际测试用例中使用这个模拟对象吗?谢谢@Yksisarvinen的回复。我尝试过这种方法,但没有成功它不工作。你能解释一下如何在实际的测试用例中使用这个模拟对象吗?