2011-04-25 158 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