views:

245

answers:

5

The current product I work on is a Windows Service written C++ and going forward all new functionality will have unit tests written for it. But this creates an interesting problem (for me at least) we do a lot Win32 calls for various things and behave accordingly, so for the unit tests to be complete it would be nice to test a variety of outputs, not just the current system state.

My question is what is the best way to mock the results of the Win32 calls? I have thought about two different methods:

1) Put all the Win32 calls used into function pointers and pass them in to the functions or classes (depending on how many times they are hit) that use them and use this to get mock results.

2) Have lots of "#ifdef UNITTEST" every where and if it is call my own special methods or have the normal ones called if not.

Am I completely off base here, or missing a fundamental piece of knowledge?

Thanks

A: 

When possible, it would be better to make the events happen while not modifying the Win32 calls.

For example instead of making your own CreateFile that will fail because a file is in use, instead exclusively open the file with another program (that you call from your unit test) then run the unit test.

If you must mock some win32 call though, then it would probably be best to create a wrapper library around the sets of Win32 calls you want to make. Then you won't harm the code literacy of the main logic.

Brian R. Bondy
+4  A: 

With respect to (2), most Win32 functions which take string parameters already have their common form defined as a macro, e.g. from 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

You could certainly add a header to your project which redefines the API functions you want to simulate:

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

By redefining the name, you can avoid scattering lots of conditional compilation throughout your source code.

Matthew Xavier
This was my thought on how to do it. I would avoid changing your function signatures in order to do unit testing.
jeffamaphone
+1  A: 

Use Deviare API hook and intercept all api calls and make your unit test.

lsalamon
A: 

I would recommend to encapsulate the API calls into well factored interfaces. Then you can test your business logic by using mock objects or test doubles. You do not need to test the Windows API itself because this is already done by millions of working Windows applications.

A unit test should never involve hardware access if you do not develop hardware. It is just about testing your logic code.

frast
A: 

In the end I actually took more a C#-ish approach and created interfaces that would allow me to stub out the Win32 calls I wanted to use.

For example I had one called IRegistryOperations that contained RegOpenKey, RegQueryValueEx, RegNotifyChange and several others I was using. A default one that simply calls into the real function was created in the constructor but I also had a constructor that took the interface so I could simulate dodgy values, etc.

(Not sure if it's bad etiquette to answer my own question though)

L2Type