Pregunta

Tengo un proyecto Visual Studio 2008 C ++ 03 donde me gustaría probar una clase de una clase que use un parámetro de plantilla de rasgos que expone los métodos estáticos (diseño basado en políticas, patrón de estrategia).Estoy usando Google Test y Google Mock Frameworks.

Por ejemplo:

/// the class under test
template< typename FooTraits >
class Foo
{
public:
    void DoSomething()
    {
        FooTraits::handle_type h = FooTraits::Open( "Foo" );
        /* ... */
        FooTraits::Close( h );
    };
};

/// a typical traits structure
struct SomeTraits
{
    typedef HANDLE handle_type;
    static handle_type Open( const char* name ) { /* ... */ };
    static void Close( handle_type h ) { /* ... */ };
};

/// mocked traits that I would like to use for testing
struct MockTraits
{
    typedef int handle_type;
    static MOCK_METHOD1( Open, handle_type( const char* ) );
    static MOCK_METHOD1( Close, void( handle_type ) );
};

/// the test function
TEST( FooTest, VerifyDoSomethingWorks )
{
    Foo< MockTraits > foo_under_test;

    // expect MockTraits::Open is called once
    // expect MockTraits::Close is called once with the parameter returned from Open
    foo_under_test.DoSomething();
};

Obviamente, esto no funcionará como es.Google Mock no puede burlarse de los métodos estáticos y tendría que crear una instancia de la clase burlada en la prueba para establecer su comportamiento y expectativas.

Entonces, ¿cuál es la forma correcta de probar una clase de una clase que acepta una política de plantillas con Google Test / Google Mock?

¿Fue útil?

Solución

¿Puede hacer una clase con métodos no estáticos, cree una instancia global de él (o estática en sus rasgos) y haga que su clase de rasgos le difere a ella?

Entonces, para aclarar la idea que se inspiró en el comentario de Rob:

struct FunnyDoodad
{
   FunnyDoodad();
   ~FunnyDoodad();

   MOCK_METHOD1( Open, HANDLE( const char* ) );
   MOCK_METHOD1( Close, void( handle_type ) );

};

struct FunnyGlobal {
  FunnyGlobal() : pimpl() {}
  ~FunnyGlobal() { delete pimpl; }

  // You'd want some protection here rather than just dereferencing.
  // it's the whole point.  I'd suggest using whatever unit test assertion
  // mechanism your framework uses and make it a fatal check.    
  handle_type Open(char const* name) { return pimpl->Open(name); }
  void Close(handle_type h) { pimpl->Close(h); }
private:
   FunnyDoodad * pimpl;

  friend struct FunnyDoodad;

  void register(FunnyDoodad* p) { pimpl = p; }
  void deregister() { pimpl = 0; }
};

FunnyGlobal funnyGlobal;

FunnyDoodad::FunnyDoodad() { funnyGlobal.register(this); }
FunnyDoodad::~FunnyDoodad() { funnyGlobal.deregister(); }

struct TestTraits
{
    typedef HANDLE handle_type;
    static handle_type Open( const char* name ) { return funnyGlobal.Open(name); };
    static void Close( handle_type h ) { funnyGlobal.Close(h); };
};

TEST_CASE(blah)
{
   FunnyDoodad testDoodad;

   ...
}

Me imagino que lo anterior podría ser plantificado y casi se convirtió en un patrón ... tal vez.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top