在ELF系統上,您可以使用elf_hook用您自己的模擬版本臨時替換各種功能的實際版本。
它允許您將調用從共享庫內的任何函數重定向到您自己的任意函數。
- 創建一個包含測試
- 在您的測試代碼共享庫加載共享庫動態(
dlopen
)
- 重定向要嘲笑你的測試功能(
elf_hook
)
- 現在符號任何對庫內實際函數的調用(被測代碼)都將被重定向到您的模擬函數
此方法的一個優點是您可以在需要時仍然會調用原始功能。
- 如果對於某些需要呼叫的測試,例如
getaddrinfo
,您可以調用系統版本。
- 在其他測試中,您可以使用自己的模擬版本,例如
mocked_getaddrinfo
,並讓它返回任何你想要的。
- 只要你想你可以創建許多
mocked_getaddrinfo
功能,測試多種場景
elf_hook具有以下特徵:
void* elf_hook(char const* library_filename,
void const* library_address,
char const* function_name,
void const* substitution_address);
你會使用這樣的:
#include <dlfcn.h>
#include "elf_hook.h"
void do_stuff(); // from the library under test (do_stuff calls getaddrinfo)
// our mocked function which will alter the behaviour inside do_stuff()
int mocked_getaddrinfo(const char* node,
const char* service,
const struct addrinfo* hints,
struct addrinfo** res)
{
// return a broken value to test a getaddrinfo failure
return 42;
}
// another version which actually calls the real function
int real_getaddrinfo(const char* node,
const char* service,
const struct addrinfo* hints,
struct addrinfo** res)
{
// the real getaddrinfo is available to us here, we only replace it in the shared lib
return getaddrinfo(node, service, hints, res);
}
int main()
{
const char* lib_path = "path/to/library/under/test.so";
// load the library under test
void* lib_handle = dlopen(lib_path, RTLD_LAZY);
// test 1: getraddrinfo is broken
//--------------------------------
// replace getaddrinfo with our 'mocked_getaddrinfo' version
elf_hook(lib_path, LIBRARY_ADDRESS_BY_HANDLE(lib_handle),
"getaddrinfo", mocked_getaddrinfo);
// call a function in the library under test where getaddrinfo fails
do_stuff();
// test 2: getraddrinfo is the system version
//--------------------------------
// replace getaddrinfo with our 'real_getaddrinfo' version
elf_hook(lib_path, LIBRARY_ADDRESS_BY_HANDLE(lib_handle),
"getaddrinfo", real_getaddrinfo);
// call the same function in the library, now getaddrinfo works
do_stuff();
dlclose(lib_handle);
return 0;
}
從被測庫中調用getaddrinfo
現在將調用mocked_getaddrinfo
。
elf_hook作者Anthony Shoumikhin的綜合文章是here。
(不是重複,但這可能有幫助嗎?)http://stackoverflow.com/questions/2924440/advice-on-mocking-system-calls – IdeaHat 2014-12-03 18:32:41
是我還是你想要的行爲在單元測試範圍之外進行測試,並進行集成測試?我想,這是一個迂腐點,但可以改變答案的範圍。對大多數開發者來說,這是兩個非常不同的話題 – ChrisCM 2014-12-03 18:38:56
@ChrisCM在我看來,這不是一個集成測試,因爲我不想做一個真正的部署,或者使用多臺機器。此外,我不想測試整個產品,但只有一些實現部分,如事件循環,網絡服務,流媒體。它應該是一個單一的二進制文件,完成所有的工作。你認爲它看起來像集成測試嗎? – 2014-12-03 18:46:33