2009-07-22 2 views
6

Текущий продукт, над которым я работаю, - это служба Windows, написанная на C++, и в дальнейшем все новые функции будут иметь для этого модульные тесты. Но это создает интересную проблему (по крайней мере, для меня) мы делаем много вызовов Win32 для разных вещей и ведем себя соответственно, поэтому для завершения модульных тестов было бы неплохо протестировать различные выходы, а не только текущую систему государство.Mocking и Win32 API-вызовы

Вопрос в том, что является лучшим способом издеваться над результатами вызовов Win32? Я подумал о двух разных методах:

1) Поместите все вызовы Win32, используемые в указатели на функции, и передайте их в функции или классы (в зависимости от того, сколько раз они попадают), которые используют их, и используют это, чтобы получить макет Результаты.

2) Имейте много #ifdef UNITTEST всюду, и если он вызывает мои собственные специальные методы или вызывается нормальным, если нет.

Я полностью отсюда, или отсутствует фундаментальная часть знаний?

+1

Что делать, если вам нужны аргументы для того, чтобы изменить поведение UnitTestMessageBox? #ifdef UNITTEST #undef MessageBox #define MessageBox UnitTestMessageBox #endif – Manolete

ответ

9

Что касается (2), большинство функций Win32, которые принимают параметры строки, уже имеют общую форму, определенную как макрос, например. от WINUSER.H:

WINUSERAPI 
int 
WINAPI 
MessageBoxA(
    __in_opt HWND hWnd, 
    __in_opt LPCSTR lpText, 
    __in_opt LPCSTR lpCaption, 
    __in UINT uType); 
WINUSERAPI 
int 
WINAPI 
MessageBoxW(
    __in_opt HWND hWnd, 
    __in_opt LPCWSTR lpText, 
    __in_opt LPCWSTR lpCaption, 
    __in UINT uType); 
#ifdef UNICODE 
#define MessageBox MessageBoxW 
#else 
#define MessageBox MessageBoxA 
#endif // !UNICODE 

Можно, конечно, добавить заголовок вашего проекта, который переопределяет функции API вы хотите имитировать:

#ifdef UNITTEST 
#undef MessageBox 
#define MessageBox UnitTestMessageBox 
#endif 

Переопределив имя, вы можете избежать многих условного рассеяния компиляция по всему исходному коду.

+0

Это была моя мысль о том, как это сделать. Я бы не стал менять подписи функций, чтобы выполнить модульное тестирование. –

-1

Если возможно, было бы лучше, если бы события произошли, не изменяя вызовы Win32.

Например, вместо того, чтобы сделать свой собственный CreateFile, который не будет работать, потому что файл используется, вместо этого следует открыть файл только с помощью другой программы (которую вы вызываете из тестового модуля), затем выполните единичный тест.

Если вы должны издеваться над каким-либо вызовом win32, то, вероятно, лучше всего создать библиотеку обертки вокруг наборов вызовов Win32, которые вы хотите создать. Тогда вы не повредите грамотности кода основной логики.

2

Используйте Deviare API. Перехватите и перехватите все вызовы api и сделайте свой модульный тест.

4

Я бы рекомендовал инкапсулировать вызовы API в хорошо обработанные интерфейсы. Затем вы можете протестировать свою бизнес-логику, используя макетные объекты или тестовые двойники. Вам не нужно тестировать сам Windows API, потому что это уже сделано миллионами работающих приложений Windows.

Единичный тест никогда не должен включать аппаратный доступ, если вы не разрабатываете аппаратное обеспечение. Это просто проверка вашего логического кода.

2

В конце концов, я на самом деле взял больше C# -образного подхода и создал интерфейсы, которые позволили бы мне заглушить вызовы Win32, которые я хотел использовать.

Например, я был один называется IRegistryOperations, который содержал RegOpenKey, RegQueryValueEx, RegNotifyChange и несколько других я использовал. По умолчанию тот, который просто вызывает реальную функцию, был создан в конструкторе, но у меня также был конструктор, который взял интерфейс, чтобы я мог имитировать хитроумные значения и т. Д.

(Не уверен, если это плохо этикета, чтобы ответить на мой собственный вопрос, хотя)