Mocking Win32 API

Mocking Win32 API

Post by Alvin7 » Sat, 05 Jul 2003 01:07:03



How can I use something like mock objects when calling Win API
functions like this?

[C++]

class WrMAPISession
{
public:
void Logon();
...

Quote:}

void WrMAPISession::Logon()
{
...
MAPILogonEx(....);
...

Quote:}

Write a class, which consists of one function - MAPILogonEx - and use
its instance as a parameter when calling Logon()? That doesn't sound
good.
 
 
 

Mocking Win32 API

Post by John Elric » Sat, 05 Jul 2003 01:13:11



Quote:> How can I use something like mock objects when calling Win API
> functions like this?

> [C++]

> class WrMAPISession
> {
> public:
> void Logon();
> ...
> }

> void WrMAPISession::Logon()
> {
> ...
> MAPILogonEx(....);
> ...
> }

> Write a class, which consists of one function - MAPILogonEx - and use
> its instance as a parameter when calling Logon()? That doesn't sound
> good.

Sure...why not?  Adapter Pattern.  You reduce the area of potential breakage
to a very narrow point.

You could pass it in, create a Singleton, or create a MAPIGateway
Adapter...whichever makes the most sense for your project.

I've found Adapters to be invaluable in simplifying testing.

John Elrick

 
 
 

Mocking Win32 API

Post by John Rot » Sat, 05 Jul 2003 02:13:41





> > How can I use something like mock objects when calling Win API
> > functions like this?

> > [C++]

> > class WrMAPISession
> > {
> > public:
> > void Logon();
> > ...
> > }

> > void WrMAPISession::Logon()
> > {
> > ...
> > MAPILogonEx(....);
> > ...
> > }

> > Write a class, which consists of one function - MAPILogonEx - and
use
> > its instance as a parameter when calling Logon()? That doesn't sound
> > good.

> Sure...why not?  Adapter Pattern.  You reduce the area of potential
breakage
> to a very narrow point.

> You could pass it in, create a Singleton, or create a MAPIGateway
> Adapter...whichever makes the most sense for your project.

> I've found Adapters to be invaluable in simplifying testing.

Oh, absolutely. I've found that too. There are things I couldn't have
tested adequately without them.

John Roth

- Show quoted text -

Quote:

> John Elrick

 
 
 

Mocking Win32 API

Post by Michael Feather » Sat, 05 Jul 2003 02:58:40



Quote:> How can I use something like mock objects when calling Win API
> functions like this?

> [C++]

> class WrMAPISession
> {
> public:
> void Logon();
> ...
> }

> void WrMAPISession::Logon()
> {
> ...
> MAPILogonEx(....);
> ...
> }

> Write a class, which consists of one function - MAPILogonEx - and use
> its instance as a parameter when calling Logon()? That doesn't sound
> good.

It's just a function, right?  Here are two techniques:

1) If you have your class in files named wrmapisession.h, and
wrmapisession.cpp make another file called testwrmapisession.cpp.  Is should
be empty except for this line:

   #include "wrmapisession.cpp"

Compile testwrmapisession.cpp and link it to your testharness.

When you want to mock out a function, add it to the file before the include:

   /* include whatever makes windows happy here */
   HRESULT MAPILogonEx(
     ULONG ulUIParam,
     LPTSTR lpszProfileName,
     LPTSTR lpszPassword,
     FLAGS flFlags,
     LPMAPISESSION FAR * lppSession
   ) { return S_OK; }

#include "wrmapisession.cpp"

2) You can try to make fake functions like the one above and put them in a
library and link to them rather than the rest of windows.  This one's called
'link time polymorphism' and I learned it from Brian Button.

Michael Feathers
www.objectmentor.com

 
 
 

Mocking Win32 API

Post by John Elric » Sat, 05 Jul 2003 04:44:00






SNIP

Quote:

> > Write a class, which consists of one function - MAPILogonEx - and use
> > its instance as a parameter when calling Logon()? That doesn't sound
> > good.

> It's just a function, right?  Here are two techniques:

> 1) If you have your class in files named wrmapisession.h, and
> wrmapisession.cpp make another file called testwrmapisession.cpp.  Is
should
> be empty except for this line:

Hi Michael!

Looks like a nice solution.  C++ isn't one of my languages...in Delphi I've
learned that a problem like this is a smell that there is a violation of
DIP.

That's why I'd move to an adapter based on an interface, with an interface
based factory to generate it.  Makes it _very_ easy to swap out test vs
production or different production implementations.

John Elrick

 
 
 

Mocking Win32 API

Post by Alvin7 » Sat, 05 Jul 2003 19:17:44





> Sure...why not?  Adapter Pattern.  You reduce the area of potential breakage
> to a very narrow point.

> You could pass it in, create a Singleton, or create a MAPIGateway
> Adapter...whichever makes the most sense for your project.

> I've found Adapters to be invaluable in simplifying testing.

> John Elrick

Should it look like this?

class MAPILogonAdapter
{
public:
  void DoMAPILogonEx(....) const

Quote:}

void MAPILogonAdapter::DoMAPILogonEx(....) const
{
  MAPILogonEx(....);

Quote:}

class WrMAPISession
{
public:
  void Logon(const MAPILogonAdapter& oMAPIAdapter);
  ...

Quote:}

void WrMAPISession::Logon(const MAPILogonAdapter& oMAPIAdapter)
{
  ...
  oMAPIAdapter::DoMAPILogonEx(....);
  ...

Quote:}

int SomeFunction()
{
  MAPILogonAdapter oLogonAdapter;
  WrMAPISession oSession;
  oSession.Logon(oLogonAdapter);
  ...

Quote:}

It looks a little overweighted to me - to create MAPILogonAdapter to
pass it to Logon.

--
Alvin777

 
 
 

Mocking Win32 API

Post by Alvin7 » Sat, 05 Jul 2003 19:26:18





> It's just a function, right?  Here are two techniques:

> 1) If you have your class in files named wrmapisession.h, and
> wrmapisession.cpp make another file called testwrmapisession.cpp.  Is should
> be empty except for this line:

>    #include "wrmapisession.cpp"

> Compile testwrmapisession.cpp and link it to your testharness.

> When you want to mock out a function, add it to the file before the include:

>    /* include whatever makes windows happy here */
>    HRESULT MAPILogonEx(
>      ULONG ulUIParam,
>      LPTSTR lpszProfileName,
>      LPTSTR lpszPassword,
>      FLAGS flFlags,
>      LPMAPISESSION FAR * lppSession
>    ) { return S_OK; }

> #include "wrmapisession.cpp"

> 2) You can try to make fake functions like the one above and put them in a
> library and link to them rather than the rest of windows.  This one's called
> 'link time polymorphism' and I learned it from Brian Button.

> Michael Feathers
> www.objectmentor.com

This method doesn't suite me well. Since I link my test exe with .lib,
containing all tested code.
 
 
 

Mocking Win32 API

Post by Alvin7 » Sat, 05 Jul 2003 21:35:00





> > How can I use something like mock objects when calling Win API
> > functions like this?

> > [C++]

> > class WrMAPISession
> > {
> > public:
> > void Logon();
> > ...
> > }

> > void WrMAPISession::Logon()
> > {
> > ...
> > MAPILogonEx(....);
> > ...
> > }

> > Write a class, which consists of one function - MAPILogonEx - and use
> > its instance as a parameter when calling Logon()? That doesn't sound
> > good.

> Sure...why not?  Adapter Pattern.  You reduce the area of potential breakage
> to a very narrow point.

> You could pass it in, create a Singleton, or create a MAPIGateway
> Adapter...whichever makes the most sense for your project.

> I've found Adapters to be invaluable in simplifying testing.

> John Elrick

Hm. Can you give C++ examples of creating Singleton (I know the
pattern, but no ideas how to use it in my case) and creating
MAPIGatewayAdapter?

--
Alvin777

 
 
 

Mocking Win32 API

Post by David Postil » Sat, 05 Jul 2003 22:31:08


[This followup was posted to comp.software.extreme-programming, cc: the cited
author, Alvin777]






| > > How can I use something like mock objects when calling Win API
| > > functions like this?

<snip>

| > > Write a class, which consists of one function - MAPILogonEx - and use
| > > its instance as a parameter when calling Logon()? That doesn't sound
| > > good.
| >
| > Sure...why not?  Adapter Pattern.  You reduce the area of potential breakage
| > to a very narrow point.
| >
| > You could pass it in, create a Singleton, or create a MAPIGateway
| > Adapter...whichever makes the most sense for your project.
| >
| > I've found Adapters to be invaluable in simplifying testing.
| >
| >
| > John Elrick
|
| Hm. Can you give C++ examples of creating Singleton (I know the
| pattern, but no ideas how to use it in my case) and creating
| MAPIGatewayAdapter?

"Implementing the Singleton Design Pattern"
  <http://gethelp.devx.com/techtips/cpp_pro/10min/10min0200.asp>

<davidp />

--
David Postill

 
 
 

Mocking Win32 API

Post by Michael Feather » Sun, 06 Jul 2003 00:44:21







> SNIP

> > > Write a class, which consists of one function - MAPILogonEx - and use
> > > its instance as a parameter when calling Logon()? That doesn't sound
> > > good.

> > It's just a function, right?  Here are two techniques:

> > 1) If you have your class in files named wrmapisession.h, and
> > wrmapisession.cpp make another file called testwrmapisession.cpp.  Is
> should
> > be empty except for this line:

> Hi Michael!

> Looks like a nice solution.  C++ isn't one of my languages...in Delphi
I've
> learned that a problem like this is a smell that there is a violation of
> DIP.

Yep, the real issue is: why are we mocking at all?  If I'm trying to get a
C++ class into a test harness to add a feature or do some refactoring
unrelated to the offending functions, I'll often do the dummy function trick
just to get past all of that direct API usage, to deal with one problem at a
time.

Quote:> That's why I'd move to an adapter based on an interface, with an interface
> based factory to generate it.  Makes it _very_ easy to swap out test vs
> production or different production implementations.

Adapters are great, but I don't like to "settle" the interface too soon.
Even though a signature like: "HRESULT MAPILogonEx(ULONG ulUIParam, LPTSTR
lpszProfileName, LPTSTR lpszPassword, FLAGS flFlags, LPMAPISESSION FAR *
lppSession)" is a crime against nature, often I'll mock it directly by
adding a method with exactly that signature to a class.  Then when I can go
back and forth with the mock and production classes I'll start to make
higher level methods hat eventually hide the API, often I get them by paying
attention to duplication and feature envy.  The nice thing is, with the mock
function in place, all the code that I move onto the new class can be
tested.  And, that is pretty good because it can safely grow into a healthy
abstraction, something more than just an adapter.

Michael Feathers
www.objectmentor.com

 
 
 

Mocking Win32 API

Post by Michael Feather » Sun, 06 Jul 2003 00:53:46



> [This followup was posted to comp.software.extreme-programming, cc: the
cited
> author, Alvin777]


2003






> | > > How can I use something like mock objects when calling Win API
> | > > functions like this?

> <snip>

> | > > Write a class, which consists of one function - MAPILogonEx - and
use
> | > > its instance as a parameter when calling Logon()? That doesn't sound
> | > > good.
> | >
> | > Sure...why not?  Adapter Pattern.  You reduce the area of potential
breakage
> | > to a very narrow point.
> | >
> | > You could pass it in, create a Singleton, or create a MAPIGateway
> | > Adapter...whichever makes the most sense for your project.
> | >
> | > I've found Adapters to be invaluable in simplifying testing.
> | >
> | >
> | > John Elrick
> |
> | Hm. Can you give C++ examples of creating Singleton (I know the
> | pattern, but no ideas how to use it in my case) and creating
> | MAPIGatewayAdapter?

> "Implementing the Singleton Design Pattern"
>   <http://gethelp.devx.com/techtips/cpp_pro/10min/10min0200.asp>

Wait.  Why do you want to use a singleton?

Michael Feathers
www.objectmentor.com

 
 
 

Mocking Win32 API

Post by Alvin7 » Sun, 06 Jul 2003 22:24:08





> > [This followup was posted to comp.software.extreme-programming, cc: the
>  cited
> > author, Alvin777]


>  2003





> > | > > How can I use something like mock objects when calling Win API
> > | > > functions like this?

> > <snip>

> > | > > Write a class, which consists of one function - MAPILogonEx - and
>  use
> > | > > its instance as a parameter when calling Logon()? That doesn't sound
> > | > > good.
> > | >
> > | > Sure...why not?  Adapter Pattern.  You reduce the area of potential
>  breakage
> > | > to a very narrow point.
> > | >
> > | > You could pass it in, create a Singleton, or create a MAPIGateway
> > | > Adapter...whichever makes the most sense for your project.
> > | >
> > | > I've found Adapters to be invaluable in simplifying testing.
> > | >
> > | >
> > | > John Elrick
> > |
> > | Hm. Can you give C++ examples of creating Singleton (I know the
> > | pattern, but no ideas how to use it in my case) and creating
> > | MAPIGatewayAdapter?

> > "Implementing the Singleton Design Pattern"
> >   <http://gethelp.devx.com/techtips/cpp_pro/10min/10min0200.asp>

> Wait.  Why do you want to use a singleton?

> Michael Feathers
> www.objectmentor.com

I don't want :) I was offered to use and I'd like to understand how
can I apply this pattern in my case.

Quote:> > | > You could pass it in, create a Singleton, or create a MAPIGateway

                              ^^^^^^^^^^^^^^^^^^

Quote:> > | > Adapter...whichever makes the most sense for your project.

--
Alvin777
 
 
 

Mocking Win32 API

Post by Phli » Sat, 05 Jul 2003 22:06:13



> How can I use something like mock objects when calling Win API
> functions like this?

Can't you write tests by putting a dedicated mail server on your system,
then send it real mail?

--
  Phlip
    http://www.c2.com/cgi/wiki?TestFirstUserInterfaces

 
 
 

Mocking Win32 API

Post by Alvin7 » Tue, 08 Jul 2003 05:24:26




> > How can I use something like mock objects when calling Win API
> > functions like this?

> Can't you write tests by putting a dedicated mail server on your system,
> then send it real mail?

This is what I did before. But it's hard to simulate
MAPI_E_LOGON_FAILED, MAPI_E_USER_CANCEL and other errors. Those lags
at MAPILogonEx() make tests run minutes rather than seconds.

And TDD says that I have to test domain code independently of
enviroment, isn't it?

--
Alvin777

 
 
 

Mocking Win32 API

Post by John Elric » Tue, 08 Jul 2003 21:43:07




SNIP

Quote:> Hm. Can you give C++ examples of creating Singleton (I know the
> pattern, but no ideas how to use it in my case) and creating
> MAPIGatewayAdapter?

I'm afraid my C++ isn't good enough...I just know it's possible.

John