2016-07-30 67 views
3

我正在編寫一個單元測試來檢查一些API調用。我正在使用檢查來測試。我的模塊是用CMake(idk,如果重要的話)構建的。功能嘲諷在C?

我的測試調用一個函數(我需要測試),這個函數調用另一個二進制文件。

它的簡化版本看起來像這樣。

/* unitTest.c */ 

#include "libraryAPI.h" 
void letsMakeACall(void) 
{ 
    ck_assert_eq(foo("water"), 0); 
} 

-- Module I am working on--- 
/*libraryAPI.c*/ 
#include "legacyLib.h" 

void foo(const char *drink)  
{ 

    if (checkDrink(drink)!=0) 
    { 
     return 1; 
    }else 
    { 
     return 0; 
    } 
} 


----LEGACY BINARY--- 
/*legacyLib.c*/ 

static const char* expected = "water"; 

void checkDrink(const char *drink) 
{ 
    if(drink == expected) 
    { 
     /*There are also a dozen functions being called which depend on legacy module initialisation*/ 
     return 0; 
    }else{ 
     return 1; 
    } 
} 

我想模擬來自legacyLib的響應,因爲否則它會調用幾十個函數和中斷。我最初的想法是在測試運行時添加一些ifdef條件,但這違反了指導原則。 因爲它基本上是一個呼叫攔截,我不知道它是一個最好的(或工作)解決方案。我可以用什麼來解決它?

+0

如果你想測試一個函數,它是沒有意義的「嘲笑」它。 –

+0

是的,但我想嘲笑來自我試圖測試的函數調用的函數之一的響應。 – Oreols

+2

該函數在哪裏定義?你可以使用「模擬」庫來替換實現該功能的庫嗎? –

回答

2

我也不清楚如何普遍解決這個問題,我已經貼了similar question,但在某些情況下,你可以做以下(假設你正在測試各個函數):

  1. 附上.c文件,而不是頭.h的,但經過你「重命名」用你嘲笑功能的定義指令:

    #define checkDrink checkDrink_mocked 
    // preprocessor will now replace all occurrences of "checkDrink" 
    // with "checkDrink_mocked" 
    
    int checkDrink_mocked(const char *drink); 
    #include "legacyLib.c" 
    #undef checkDrink 
    
  2. 落實改名功能:

    int checkDrink_mocked(const char *drink) 
    { 
        return 15; 
    } 
    
+0

謝謝。我認爲這是最好的解決方案。在我的情況下,它是非常簡單的getter-setter引用,所以我只是重新實現了它的模塊(對愚蠢的東西的依賴性減少:))。 – Oreols

+0

太棒了,很高興,如果它的工作。例如,如果某個'libraryAPI.c'函數從不同的模塊調用某個extern函數,然後從'libraryAPI.c'(本例中爲'checkDrink')調用一個原函數,這很容易失敗,因爲鏈接器將會然後找到原始功能。我找到了一個名爲mimick的庫([Snaipe/Mimick](https://github.com/Snaipe/Mimick))(作者提到它仍處於alpha階段),它通過更改*「全局偏移表運行時的動態模塊「*,但我沒有嘗試過(它顯然支持GCC 4.6+,Clang 3.5+,MSVC 14+)。 – Lou