簡體   English   中英

模擬非虛方法C ++(gmock)

[英]Mock non-virtual method C++ (gmock)

我有課

class CSumWnd : public CBaseWnd
{

 private:
 bool MethodA()
}

請你能幫助如何模擬MethodA()而不做虛擬,我不明白hi-perf依賴注入的概念

這意味着您必須模擬生產代碼。 使用你的例子:

CSumWind類定義:

class CSumWnd : public CBaseWnd
{

 private:
 bool MethodA()
};

模擬CSumWnd類定義:

class MockCSumWnd : public CBaseWnd
{

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

生產類必須使用CSumWindCSumWind進行測試。 現在,在測試中提供在生產代碼和MockCSumWnd類中使用CSumWind類的模板。

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

private:
  CSumWndClass sumWnd;
};

在生產中實例化TestedClass

TestedClass <CSumWnd> obj;

測試可執行文件中TestedClass對象的實例化:

TestedClass <MockCSumWnd> testObj;

如果您不想更改現有代碼,這里是我正在開發的VC ++的特定解決方案( https://github.com/mazong1123/injectorpp )。 簡短的步驟是:

  1. 利用DbgHelp.h檢索類的所有方法符號和內存地址。 基本上它在運行時從.pdb文件中檢索元信息。
  2. 將用戶輸入與模擬方法符號與步驟1的輸出進行比較,獲取to-mock方法的內存地址。
  3. 利用windows api WriteProcessMemory來改變to-mock方法的入口字節,類似於:__ asm {move eax,1; RET}。

我們把關鍵代碼放在這里。

  1. 檢索方法的符號和類的地址。 以下是實施的關鍵思路。 完整的源代碼可以在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. 如何注入magic 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); } 

試試CppFreeMock這里提到的其他一些。

例:

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());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM