CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 1 of 1
  1. #1
    Join Date
    Feb 2007
    Posts
    20

    Mocking a class whose constructor is called by a "black box"

    I am trying to isolate for the purpose of unit testing class A which uses internally class Socket (a facade for socket function calls). The tools I am using are Visual Studio 2005, Visual Assert using the WinUnit interface, and hippomocks, but it is unimportant.

    For the purpose of unit testing, class A is a black box, it creates Socket objects on a need-to basis, most importantly a single Socket object at a time, and it doesn't have any constructors that take Socket references or pointers, so I cannot simply pass a mock created by the mocking framework to an A constructor.

    The solution I came up with incorporates elements of the NVI (nonvirtual interface) and Pimpl patterns and works as follows: Define an interface (all methods pure virtual) ISocket class (required by my mocking framework) that provides the same interface as the real Socket class, and then define a mock Socket class for testing purposes that contains a static ISocket Pimpl and non-virtual pass-throughs. Additionally, the mock Socket class contains static queue<string>'s of read and write "buffers" that allow me, through the nonvirtual read and write pass-throughs, to set up the messages that the socket will "receive" during the unit test, and to inspect messages "sent" by the socket at the end of the unit test. I am not happy about the Pimpl and "buffers" being static, but I don't see any way around it, besides using global variables. Either way, I can't have a unit test that involves two or more A objects. More importantly, if any A method created more than one Socket object at a time, this whole scheme would be a non-starter.

    I would like to know if anyone here can think of or has employed in the past a better approach. Any and all feedback will be appreciated, thanks.

    Note that the code below is not the actual code---for brevity I combined the .h and .cpp file contents whereas in reality class definitions (.h) and their static variables and methods definitions (.cpp) are separate.

    Code:
    class ISocket
    {
    public:
        int read ( void *, int, bool, int ) = 0;
        int write ( void const *, int ) = 0;
    };
    
    class Socket
    {
    public:
        // pass-throughs
        int read ( void * const buf,
                   int    const size,
                   bool   const blocking,
                   int    const flags )
        {
            int const err = this->pimpl_->read( buf, size, blocking, flags );
            strcpy_s( (char*)buf, size, Socket::reads_.front().c_str() )
            Socket::reads.pop_front();
            return err;
        }
    
        int write ( void const * const buf, int const size )
        {
            Socket::writes_.push_back( (char*)buf );
            return this->pimpl_->write( buf, size );
        }
    
    public:
        static ISocket * pimpl_;
        static queue<string> reads_;
        static queue<string> writes_;
    }
    
    BEGIN_TEST(foo_FirstCall_ReturnFalse)
    {
        MockRepository mocks;
        Socket::pimpl_ = mocks.InterfaceMock<ISocket>();
        Socket::reads_.clear();
        Socket::writes_.clear();
        Socket::reads_.push_back( string("input msg 1") );
        Socket::reads_.push_back( string("input msg 2") );
    
        A a;
        bool err = a.foo();
    
        ASSERT_EQUAL(false, err,
                     "return value on first call is not false");
        ASSERT_TRUE(1 <= Socket::writes_.size(),
                     "no messages were sent");
        ASSERT_EQUAL(1, Socket::writes_.size(),
                     "more than one message was sent");
        ASSERT_EQUAL("output msg", Socket::writes_.front(),
                     "wrong output message sent");
    }
    END_TEST
    Last edited by natskvi; February 9th, 2012 at 07:42 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured