"특성"템플릿 매개 변수를 사용하는 객체 테스트
-
11-12-2019 - |
문제
정적 메소드를 노출하는 특성 템플릿 매개 변수를 사용하는 클래스를 사용하는 클래스를 사용하는 Visual Studio 2008 C ++ 03 프로젝트가 있습니다 (정책 기반 디자인, 전략 패턴).Google 테스트 및 Google 모의 프레임 워크를 사용하고 있습니다.
예 :
/// 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();
};
.
분명히 이것은 그렇게 작동하지 않습니다.Google 모의는 정적 방법을 모의 할 수 없으며 테스트에서 조롱 된 클래스의 인스턴스를 만들어 행동과 기대를 설정해야합니다.
Google 테스트 / Google 모의를 사용하여 템플릿 정책을 수락하는 클래스를 테스트하는 올바른 방법은 무엇입니까?
해결책
정적이 아닌 메소드로 클래스를 만들고, 글로벌 인스턴스를 작성하거나, 귀하의 특성 클래스가 그대로 지연시킬 수 있습니까?
그래서, 롭의 코멘트에서 영감을 얻은 아이디어를 명확히하기 위해 :
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;
...
}
.
위의 템플릿을 상상하고 거의 패턴으로 바뀌었을 것입니다 ... 어쩌면.
제휴하지 않습니다 StackOverflow