The implications of using boost :: shared_ptr and AMOP

I am trying to write mocks using amop . I am using Visual Studio 2008.

I have this interface class:

struct Interface {
   virtual void Activate() = 0;
};

      

and this other class that receives pointers to this one Interface

, for example:

struct UserOfInterface {
   void execute(Interface* iface) {
      iface->Activate();
   }
};

      

So I am trying to write some test code like this:

amop::TMockObject<Interface> mock;
mock.Method(&Interface::Activate).Count(1);

UserOfInterface user;
user.execute((Interface*)mock);

mock.Verifiy();

      

It works! So far so good, but what I really want is boost :: shared_ptr in the execute () method, so I write this:

struct UserOfInterface {
   void execute(boost::shared_ptr<Interface> iface) {
      iface->Activate();
   }
};

      

How should the test code be? I've tried some things like:

amop::TMockObject<Interface> mock;
mock.Method(&Interface::Activate).Count(1);

UserOfInterface user;
boost::shared_ptr<Interface> mockAsPtr((Interface*)mock);
user.execute(mockAsPtr);

mock.Verifiy();

      

It compiles, but clearly fails because at the end of the scope the "mock" variable gets a double kill (due to the "mock" stack variable and shared_ptr).

I also tried creating a 'mock' variable on the heap:

amop::TMockObject<Interface>* mock(new amop::TMockObject<Interface>);
mock->Method(&Interface::Activate).Count(1);

UserOfInterface user;
boost::shared_ptr<Interface> mockAsPtr((Interface*)*mock);
user.execute(mockAsPtr);

mock->Verifiy();

      

But that doesn't work, somehow it goes into an infinite loop before I had a problem with boost not detecting the destructor for the mocked object when the shared_ptr tried to delete the object.

Has anyone used amop with boost :: shared_ptr successfully?

+2


source to share


5 answers


You might want to try using a more explicit cast. I'm not sure if this will work, but try it.



// Get the mock generator
boost::shared_ptr< amop::TMockObject<Interface> > mock
    = boost::make_shared< amop::TMockObject<Interface> >;
// Get the mocked interface
boost::shared_ptr<Interface> imock = boost::dynamic_pointer_cast<Interface>(mock);

// Setup mock usage expectations
mock->Method(&Interface::Activate).Count(1);

// Run the test
UserOfInterface user;
user.execute(imock);

// Verify the expectations were met
mock->Verifiy();

      

0


source


Well, I've never used an amp, but perhaps this amplification pattern will help.

To create boost shared_ptr you can also use

boost::shared_ptr<Interface> mock(new amop::TMockObject<Interface>());

      



This way, the mock object is not created on the stack and only destroyed if the reference count in the shared_ptr reaches zero. Since this is essentially the same as the second try, one more tip:

If you are facing problems similar to C ++ not finding the correct destructor, you can inject a virtual destructor into the base class (interface). Does the amulet allow this?

class Interface{
  virtual ~Interface() { }
  ...
};

      

0


source


You can give shared_ptr a custom functor that will be called instead of deleting when the reference count is zero.

Then the code will look like this (I have not tried to compile it):

struct NoOpDel
{
void operator() (void *) { }
}

amop::TMockObject<Interface> mock;
mock.Method(&Interface::Activate).Count(1);

UserOfInterface user;
boost::shared_ptr<Interface> imock((Interface*)mock, NoOpDel())
user.execute(imock);

mock.Verify();

      

See Boost API doc for details , you are interested in this constructor:

template<class Y, class D> shared_ptr(Y * p, D d);

      

0


source


Disclaimer: I am the author of HippoMocks

By using HippoMocks, you can specify that you expect the destructor to be called at the end of your test. It also implicitly confirms your expectations at the end of your test. Thus, it can even guard against a stray shared_ptr on the heap that you forgot to delete, or a class that doesn't take ownership or forgets to delete a pointer in case you're not using a shared_ptr.

0


source


There is a way to use shared_ptr with amop

struct Interface {
   virtual ~Interface() {}
   virtual void Activate() = 0;
};

TEST(MockObjectMethodDestructor)
{  
    TMockObject<Interface> mock;

    mock.Method(Destructor());

    boost::shared_ptr<Interface> ptr((IInterface*)mock);

    ptr.reset();
}

      

0


source







All Articles