Question

J'ai un projet Visual Studio 2008 C ++ 03 où j'aimerais assister à tester une classe qui utilise un paramètre de modèle de traits qui expose des méthodes statiques (conception basée sur des stratégies, modèle de stratégie).J'utilise Google Test et Google Frameworks.

Par exemple:

/// 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();
};

Évidemment, cela ne fonctionnera pas comme.Google Mock ne peut pas se moquer de méthodes statiques et je devrais créer une instance de la classe moquée dans le test pour définir son comportement et ses attentes.

Alors, quelle est la bonne façon de tester une classe une classe qui accepte une stratégie de modèle utilisant Google Test / Google Mock?

Était-ce utile?

La solution

Pouvez-vous créer une classe avec des méthodes non statiques, créez une instance globale de celle-ci (ou statique dans vos traits) et faites-le reporter votre classe de traits?

Ainsi, pour clarifier l'idée qui a été inspirée par le commentaire 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;

   ...
}

J'imagine que ce qui précède pourrait être modelé et presque transformé en un motif ... peut-être.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top