2011-04-25 160 views

回答

11

这意味着概念你将不得不对你的生产代码进行模板化。使用你的例子:

CSumWind类定义:

class CSumWnd : public CBaseWnd 
{ 

private: 
bool MethodA() 
}; 

嘲笑CSumWnd类的定义:它必须与嘲笑类CSumWind测试

class MockCSumWnd : public CBaseWnd 
{ 

private: 
MOCK_METHOD(MethodA, bool()); 
}; 

生产类。现在它成为在测试中使用CSumWind类生产代码和MockCSumWnd类的模板。在生产​​

template <class CSumWndClass> 
class TestedClass { 
//... 
    void useSumWnd(const CSumWndClass &a); 

private: 
    CSumWndClass sumWnd; 
}; 

实例化:

实例化对象的​​
TestedClass <CSumWnd> obj; 

测试可执行文件:

TestedClass <MockCSumWnd> testObj; 
+0

为了让您的“生产”代码干净,我发现它有用执行此操作: template class TestedClassTemplate {...},然后执行typedef TestedClassTemplate TestedClass; – smehmood 2011-04-28 19:28:53

+1

请参阅http://stackoverflow.com/q/1127918/49972了解您提出建议后果的信息。 – 2011-05-26 20:19:57

+0

我在'MOCK_METHOD(MethodA,bool())中遇到问题;''https://stackoverflow.com/questions/46542373/how-to-mock-non-virtual-methods-using-googlemock?noredirect=1#comment80038793_46542373我收到上述问题中指定的错误 – CMouse 2017-10-03 10:33:44

1

尝试CppFreeMock和其他一些人提到here

例子:

string func() { 
    return "Non mocked."; 
} 

TEST(HelloWorld, First) { 
    EXPECT_CALL(*MOCKER(func), MOCK_FUNCTION()).Times(Exactly(1)) 
     .WillOnce(Return("Hello world.")); 
    EXPECT_EQ("Hello world.", func()); 
} 
+1

对于我来说,第二个链接指向OneDrive登录。另外,不要仅仅使用“这里”作为描述,而应该提供更具描述性的描述性内容,以便在未来链接死亡的情况下仍能找到文档。 – PeterJ 2014-09-28 05:02:00

+0

我没有足够的信誉在一个答案中添加2个以上的链接,更新“here”的链接,无需再登录。完整的文档可以在github中找到。 – Louix 2014-09-28 14:11:09

0

如果你不想改变现有的代码,这里是VC特定的解决方案++我的工作(https://github.com/mazong1123/injectorpp)。简要步骤如下:

  1. 利用DbgHelp.h检索类的所有方法的符号和内存地址。基本上它在运行时从.pdb文件中检索元信息。
  2. 将用户输入模拟方法符号与步骤1的输出进行比较,获取模拟方法的存储器地址。
  3. 利用windows api WriteProcessMemory来改变模拟方法的入口字节,类似于:__asm {move eax,1; RET}。

让我们把关键代码放在这里。

  1. 检索方法的符号和类的地址。以下是实施的关键思想。完整的源代码是在availiable https://github.com/mazong1123/injectorpp/blob/master/injectorpp/ClassResolver.cpp

    // Retrieve class symbol. 
    if (SymGetTypeFromName(this->m_hProcess, modBase, className.c_str(), classSymbol) == FALSE) 
    { 
        throw; 
    } 
    
    // Get children of class - which are methods. 
    DWORD numChildren = 0; 
    if (SymGetTypeInfo(this->m_hProcess, classSymbol->ModBase, classSymbol->TypeIndex, TI_GET_CHILDRENCOUNT, &numChildren) == FALSE) 
    { 
        throw; 
    } 
    
    // Get methods info. 
    if (SymGetTypeInfo(this->m_hProcess, classSymbol->ModBase, classSymbol->TypeIndex, TI_FINDCHILDREN, methods) == FALSE) 
    { 
        throw; 
    } 
    
    // Retrieve all methods. 
    for (DWORD i = 0; i < numChildren; ++i) 
    { 
        ULONG curChild = methods->ChildId[i]; 
    
        // Resolve function. 
        Function resolvedFunction; 
        this->m_functionResolver->Resolve(classSymbol->ModBase, curChild, resolvedFunction); 
    
        // Add the resolved function to the output. 
        resolvedMethods.push_back(resolvedFunction); 
    } 
    
  2. 步骤2是繁琐。这只是文本比较和处理。

  3. 如何注入魔力ASM改变方法的行为:(完整的源代码可在https://github.com/mazong1123/injectorpp/blob/master/injectorpp/BehaviorChanger.cpp

    // A magic function to change the function behavior at runtime 
    // 
    // funcAddress - The address of the function to be changed from. 
    // expectedReturnValue - The return value should be changed to. 
    void BehaviorChanger::ChangeFunctionReturnValue(ULONG64 funcAddress, int expectedReturnValue) 
    { 
    
    
    // The purpose of this method is to change the return value 
    // to what ever int value we expected. 
    
    // Therefore, we just need to inject below asm to the header of specific function: 
    // 
    // mov eax, expectedValue 
    // ret 
    // 
    // Above asm code tells the function to return expectedValue immediately. 
    
    // Now let's prepare the asm command. 
    byte asmCommand[6]; 
    
    // mov 
    asmCommand[0] = 0xB8; 
    
    // The value. 
    asmCommand[1] = expectedReturnValue & 0xFF; 
    asmCommand[2] = (expectedReturnValue >> 8) & 0xFF; 
    asmCommand[3] = (expectedReturnValue >> 16) & 0xFF; 
    asmCommand[4] = (expectedReturnValue >> 24) & 0xFF; 
    
    // ret 
    asmCommand[5] = 0xC3; 
    
    WriteProcessMemory((HANDLE)-1, (void*)funcAddress, asmCommand, 6, 0); 
    } 
    
+0

看起来很有趣。我很想看到GCC/Clang类似的东西。 – hedayat 2017-09-02 10:28:04

+0

@hedayat我打算这样做。最近我几乎完成了x86 Windows部分。保持调谐。 – 2017-10-01 06:39:03