IntroductionBy using ABI and template techniques, make AMOP different from other C++ Mock Object library. Here is the basic usage for this library. And please read the Unit-Test in the source for more details. Details#include <UnitTest++.h>
#include "../MockObject.h"
#include <string>
using namespace amop;
//------------------------------------------------------------------
class IInterface
{
public:
virtual void SimpleFunction() = 0;
virtual void SimpleFunctionWithParams(float, std::string, const char*) = 0;
virtual int SimpleFunctionWithParamsAndReturn(float, std::string, const char*) = 0;
virtual void SimpleFunctionWithAlotParams(float, int, float, int, std::string) = 0;
virtual int SimpleFunctionWithReturn() = 0;
virtual int& SimpleFunctionWithRefReturn() = 0;
virtual void SimpleConstFunction() const = 0;
virtual std::string ComplexFunction(const std::string& crs,
std::string& rs, std::string s) = 0;
virtual std::string ComplexConstFunction(const std::string& crs,
std::string& rs, std::string s) const = 0;
virtual void PolicyTestFunction(
std::string& str
, std::string* pointedStr
, char* const buffer
);
virtual ~IInterface(){}
};
//------------------------------------------------------------------
TEST(CreateMockObject)
{
TMockObject<IInterface> mock;
CHECK( (IInterface*)mock );
}
//------------------------------------------------------------------
TEST(MockObjectNotImplementedThrowSimpleFunction)
{
TMockObject<IInterface> mock;
CHECK((IInterface*)mock);
CHECK_THROW(((IInterface*)mock)->SimpleFunction(), TNotImplementedException);
}
//------------------------------------------------------------------
TEST(MockObjectNotImplementedThrowComplexFunction)
{
TMockObject<IInterface> mock;
CHECK((IInterface*)mock);
std::string crs, rs, s;
CHECK_THROW(
((IInterface*)mock)->ComplexFunction(crs, rs, s),
TNotImplementedException);
}
//mockSubscriber.method("receive").expects(once()).with( eq(message) );
//------------------------------------------------------------------
TEST(MockObjectMethodSimple)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunction);
mock.Method(&IInterface::SimpleFunctionWithAlotParams);
((IInterface*)mock)->SimpleFunction();
((IInterface*)mock)->SimpleFunctionWithAlotParams(0, 0, 0, 0, std::string());
}
//------------------------------------------------------------------
TEST(MockObjectMethodComplex)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::ComplexFunction)
.Will("Test Result");
std::string crs, rs, s;
std::string result =
((IInterface*)mock)->ComplexFunction(crs, rs, s);
CHECK_EQUAL("Test Result", result.c_str());
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleWithReturn)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Will(22);
mock.Method(&IInterface::SimpleFunctionWithRefReturn)
.Will(1262);
CHECK_EQUAL(22, ((IInterface*)mock)->SimpleFunctionWithReturn());
CHECK_EQUAL(1262, ((IInterface*)mock)->SimpleFunctionWithRefReturn());
}
//------------------------------------------------------------------
TEST(MockObjectMethodConstSimple)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleConstFunction);
((IInterface*)mock)->SimpleConstFunction();
}
struct SimpleException : public std::exception
{
int value;
SimpleException(int v)
: std::exception()
, value(v){
}
};
void ThisThrows(){
throw SimpleException(42);
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleWithThrow)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Throws(std::exception());
CHECK_THROW(((IInterface*)mock)->SimpleFunctionWithReturn(), std::exception );
mock.Verify();
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleWithInheritedThrow)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Throws(SimpleException(22));
CHECK_THROW(((IInterface*)mock)->SimpleFunctionWithReturn(), std::exception);
mock.Verify();
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleWithManyThrow)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Throws(SimpleException(22));
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Wills(42);
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Throws(SimpleException(142));
try{
((IInterface*)mock)->SimpleFunctionWithReturn();
CHECK(false);
}catch(SimpleException & se){
CHECK_EQUAL(22, se.value);
}
CHECK_EQUAL(42, ((IInterface*)mock)->SimpleFunctionWithReturn());
try{
((IInterface*)mock)->SimpleFunctionWithReturn();
CHECK(false);
}catch(SimpleException & se){
CHECK_EQUAL(142, se.value);
}
mock.Verify();
}
//------------------------------------------------------------------
TEST(MockObjectMethodConstComplex)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::ComplexConstFunction)
.Will("Test Result");
std::string crs, rs, s;
std::string result =
((IInterface*)mock)->ComplexConstFunction(crs, rs, s);
CHECK_EQUAL("Test Result", result.c_str());
}
//------------------------------------------------------------------
TEST(MockObjectMethodMultiWithReturn)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Wills(22).Wills(11);
CHECK_EQUAL(22, ((IInterface*)mock)->SimpleFunctionWithReturn());
CHECK_EQUAL(11, ((IInterface*)mock)->SimpleFunctionWithReturn());
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleExpect)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithParams)
.Expect<0>(21.0f)
.Expect<1>("Hello World")
.Expect<2>("SomeText");
((IInterface*)mock)->SimpleFunctionWithParams(21.0f, "Hello World", "SomeText");
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleExpectPolicy)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::PolicyTestFunction)
.Expect<0>("First")
.Expect<1>(Policy::Pointer("Second"))
.Expect<2>(Policy::Array("Third", strlen("Third") + 1) );
std::string first = "First";
std::string second = "Second";
char buf[] = "Third";
((IInterface*)mock)->PolicyTestFunction(first, &second, buf) ;
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleExpectThrow)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithParams)
.Expect<0>(21.0f)
.Expect<1>("Hello World")
.Expect<2>("SomeText");
CHECK_THROW( ((IInterface*)mock)->SimpleFunctionWithParams(2.0f, "Hllo World", "SomeTet")
, TNotEqualException );
}
//------------------------------------------------------------------
TEST(MockObjectMethodMultipleExpect)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithParams)
.Expects<0>(1.0f) .Expects<0>(2.0f) .Expects<0>(3.0f)
.Expects<1>("Hello 1") .Expects<1>("Hello 2") .Expects<1>("Hello 3")
.Expects<2>("SomeText1").Expects<2>("SomeText2") .Expects<2>("SomeText3");
((IInterface*)mock)->SimpleFunctionWithParams(1.0f, "Hello 1", "SomeText1");
((IInterface*)mock)->SimpleFunctionWithParams(2.0f, "Hello 2", "SomeText2");
((IInterface*)mock)->SimpleFunctionWithParams(3.0f, "Hello 3", "SomeText3");
}
//------------------------------------------------------------------
TEST(MockObjectMethodMultipleExpectThrow)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithParams)
.Expects<0>(1.0f) .Expects<0>(2.0f) .Expects<0>(3.0f)
.Expects<1>("Hello 1") .Expects<1>("Hello 2") .Expects<1>("Hello 3")
.Expects<2>("SomeText1").Expects<2>("SomeText2") .Expects<2>("SomeText3");
CHECK_THROW( ((IInterface*)mock)->SimpleFunctionWithParams(2.0f, "Hllo 1", "SmeText1")
, TNotEqualException );
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleExpectAndReturn)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithParamsAndReturn)
.Expect<0>(21.0f)
.Expect<1>("Hello World")
.Expect<2>("SomeText")
.Will(2);
CHECK_EQUAL(2,
((IInterface*)mock)->SimpleFunctionWithParamsAndReturn(21.0f, "Hello World", "SomeText") );
CHECK_THROW(
((IInterface*)mock)->SimpleFunctionWithParamsAndReturn(1.0f, "Heo World", "SoText")
, TNotEqualException );
}
//------------------------------------------------------------------
TEST(MockObjectMethodRedirectFreeFunc)
{
static std::string firstRecv;
static std::string secondRecv;
static std::string thirdRecv;
struct Local
{
static std::string HandleRedirect(const std::string& crs,
std::string& rs, std::string s)
{
firstRecv = crs;
secondRecv = rs;
thirdRecv = s;
rs = "CHANGED";
return "RESULT";
}
};
TMockObject<IInterface> mock;
mock.Method(&IInterface::ComplexFunction)
.Redirect(&Local::HandleRedirect);
std::string second = "Second";
std::string result =
((IInterface*)mock)->ComplexFunction("First", second, "Third");
CHECK_EQUAL("RESULT", result.c_str());
CHECK_EQUAL("First", firstRecv.c_str());
CHECK_EQUAL("Second", secondRecv.c_str());
CHECK_EQUAL("Third", thirdRecv.c_str());
CHECK_EQUAL("CHANGED", second.c_str());
}
//------------------------------------------------------------------
struct TestRedirectLocal
{
std::string HandleRedirect(const std::string& crs,
std::string& rs, std::string s)
{
firstRecv = crs;
secondRecv = rs;
thirdRecv = s;
rs = "CHANGED";
return "RESULT";
}
std::string firstRecv;
std::string secondRecv;
std::string thirdRecv;
};
//------------------------------------------------------------------
TEST(MockObjectMethodRedirectMethod)
{
TestRedirectLocal local;
TMockObject<IInterface> mock;
mock.Method(&IInterface::ComplexFunction)
.Redirect(&local, &TestRedirectLocal::HandleRedirect);
std::string second = "Second";
std::string result =
((IInterface*)mock)->ComplexFunction("First", second, "Third");
CHECK_EQUAL("RESULT", result.c_str());
CHECK_EQUAL("First", local.firstRecv.c_str());
CHECK_EQUAL("Second", local.secondRecv.c_str());
CHECK_EQUAL("Third", local.thirdRecv.c_str());
CHECK_EQUAL("CHANGED", second.c_str());
}
//------------------------------------------------------------------
TEST(MockObjectMethodSet)
{
TestRedirectLocal local;
TMockObject<IInterface> mock;
mock.Method(&IInterface::ComplexFunction)
.Set<1>("CHANGED")
.Will("");
std::string second = "Second";
std::string result =
((IInterface*)mock)->ComplexFunction("First", second, "Third");
CHECK_EQUAL("CHANGED", second.c_str());
}
//------------------------------------------------------------------
TEST(MockObjectMethodSimpleSetPolicy)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::PolicyTestFunction)
.Set<0>("First")
.Set<1>(Policy::Pointer("Second"))
.Set<2>(Policy::Array("Third", strlen("Third") + 1) );
std::string first;
std::string second;
char buf[sizeof("Third")];
((IInterface*)mock)->PolicyTestFunction(first, &second, buf) ;
CHECK_EQUAL( "First", first.c_str() );
CHECK_EQUAL( "Second", second.c_str() );
CHECK( memcmp("Third", buf, sizeof("Third") )== 0 );
}
//------------------------------------------------------------------
TEST(MockObjectMethodSetMultiple)
{
TestRedirectLocal local;
TMockObject<IInterface> mock;
mock.Method(&IInterface::ComplexFunction)
.Sets<1>("C1").Sets<1>("C2").Sets<1>("C3")
.Will("");
std::string second = "Second";
((IInterface*)mock)->ComplexFunction("First", second, "Third");
CHECK_EQUAL("C1", second.c_str());
((IInterface*)mock)->ComplexFunction("First", second, "Third");
CHECK_EQUAL("C2", second.c_str());
((IInterface*)mock)->ComplexFunction("First", second, "Third");
CHECK_EQUAL("C3", second.c_str());
}
//------------------------------------------------------------------
TEST(MockObjectMethodAddCallCount)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::ComplexFunction).Will(std::string());
std::string second = "Second";
((IInterface*)mock)->ComplexFunction("First", second, "Third");
((IInterface*)mock)->ComplexFunction("First", second, "Third");
((IInterface*)mock)->ComplexFunction("First", second, "Third");
CHECK_EQUAL(3u, mock.Method(&IInterface::ComplexFunction).Count());
}
//------------------------------------------------------------------
TEST(MockObjectMethodReset)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunction);
mock.Clear();
CHECK_THROW(((IInterface*)mock)->SimpleFunction(), TNotImplementedException);
}
//------------------------------------------------------------------
TEST(MockObjectMethodDestructor)
{
TMockObject<IInterface> mock;
mock.Method(Destructor());
delete ((IInterface*)mock);
}
//------------------------------------------------------------------
TEST(MockObjectMethodVerifyCallCount)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunction)
.Count(3);
((IInterface*)mock)->SimpleFunction();
((IInterface*)mock)->SimpleFunction();
((IInterface*)mock)->SimpleFunction();
// It will not throw
mock.Verify();
((IInterface*)mock)->SimpleFunction();
CHECK_THROW(mock.Verify(), TCallCountException);
}
//------------------------------------------------------------------
TEST(MockObjectMethodVerifyExpects)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithParams)
.Expects<0>(1.0f).Expects<0>(2.0f).Expects<0>(3.0f)
.Expect<1>("")
.Expect<2>("");
((IInterface*)mock)->SimpleFunctionWithParams(1.0f, "", "");
((IInterface*)mock)->SimpleFunctionWithParams(2.0f, "", "");
((IInterface*)mock)->SimpleFunctionWithParams(3.0f, "", "");
// It will not throw
mock.Verify();
((IInterface*)mock)->SimpleFunctionWithParams(4.0f, "", "");
CHECK_THROW(mock.Verify(), TCallCountException);
}
//------------------------------------------------------------------
TEST(MockObjectMethodWillsCallCountException)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Wills(1)
.Wills(2)
.Wills(3);
((IInterface*)mock)->SimpleFunctionWithReturn();
((IInterface*)mock)->SimpleFunctionWithReturn();
((IInterface*)mock)->SimpleFunctionWithReturn();
CHECK_THROW(((IInterface*)mock)->SimpleFunctionWithReturn()
, TCallCountException);
}
//------------------------------------------------------------------
TEST(MockObjectMethodWillsCallCountVerify)
{
TMockObject<IInterface> mock;
mock.Method(&IInterface::SimpleFunctionWithReturn)
.Wills(1)
.Wills(2)
.Wills(3);
CHECK_THROW(mock.Verify(), TCallCountException);
}
//------------------------------------------------------------------
class ISimple1
{
public:
virtual void SimpleFunction() = 0;
virtual int SimpleFunctionWithReturn() = 0;
virtual ~ISimple1();
};
//------------------------------------------------------------------
class ISimple2
{
public:
virtual void SimpleFunction() = 0;
virtual int SimpleFunctionWithReturn() = 0;
virtual ~ISimple2();
};
//------------------------------------------------------------------
TEST(TwoInterfaces_noneImplemented)
{
TMockObject<ISimple1> mock1;
TMockObject<ISimple2> mock2;
CHECK_THROW(((ISimple1*)mock1)->SimpleFunction(), TNotImplementedException);
CHECK_THROW(((ISimple2*)mock2)->SimpleFunction(), TNotImplementedException);
CHECK_THROW(((ISimple1*)mock1)->SimpleFunctionWithReturn(), TNotImplementedException);
CHECK_THROW(((ISimple2*)mock2)->SimpleFunctionWithReturn(), TNotImplementedException);
}
//------------------------------------------------------------------
TEST(TwoInterfaces_oneSimpleImplemented)
{
TMockObject<ISimple1> mock1;
TMockObject<ISimple2> mock2;
mock1.Method(&ISimple1::SimpleFunction);
((ISimple1*)mock1)->SimpleFunction();
CHECK_THROW(((ISimple2*)mock2)->SimpleFunction(), TNotImplementedException);
CHECK_THROW(((ISimple1*)mock1)->SimpleFunctionWithReturn(), TNotImplementedException);
CHECK_THROW(((ISimple2*)mock2)->SimpleFunctionWithReturn(), TNotImplementedException);
}
//------------------------------------------------------------------
TEST(TwoInterfaces_bothSimpleImplemented)
{
TMockObject<ISimple1> mock1;
TMockObject<ISimple2> mock2;
mock1.Method(&ISimple1::SimpleFunction);
mock2.Method(&ISimple2::SimpleFunction);
((ISimple1*)mock1)->SimpleFunction();
((ISimple2*)mock2)->SimpleFunction();
CHECK_THROW(((ISimple1*)mock1)->SimpleFunctionWithReturn(), TNotImplementedException);
CHECK_THROW(((ISimple2*)mock2)->SimpleFunctionWithReturn(), TNotImplementedException);
}
//------------------------------------------------------------------
TEST(TwoInterfaces_oneReturnImplemented)
{
TMockObject<ISimple1> mock1;
TMockObject<ISimple2> mock2;
int expected1 = 1;
mock1.Method(&ISimple1::SimpleFunctionWithReturn)
.Will(expected1);
CHECK_THROW(((ISimple1*)mock1)->SimpleFunction(), TNotImplementedException);
CHECK_THROW(((ISimple2*)mock2)->SimpleFunction(), TNotImplementedException);
int got = ((ISimple1*)mock1)->SimpleFunctionWithReturn();
CHECK_EQUAL(expected1, got);
CHECK_THROW(((ISimple2*)mock2)->SimpleFunctionWithReturn(), TNotImplementedException);
}
//------------------------------------------------------------------
TEST(TwoInterfaces_bothReturnImplemented)
{
TMockObject<ISimple1> mock1;
TMockObject<ISimple2> mock2;
int expected1 = 1;
int expected2 = 2;
mock1.Method(&ISimple1::SimpleFunctionWithReturn)
.Will(expected1);
mock2.Method(&ISimple2::SimpleFunctionWithReturn)
.Will(expected2);
CHECK_THROW(((ISimple1*)mock1)->SimpleFunction(), TNotImplementedException);
CHECK_THROW(((ISimple2*)mock2)->SimpleFunction(), TNotImplementedException);
int got;
got = ((ISimple1*)mock1)->SimpleFunctionWithReturn();
CHECK_EQUAL(expected1, got);
got = ((ISimple2*)mock2)->SimpleFunctionWithReturn();
CHECK_EQUAL(expected2, got);
}
|
Hi very nice framework!!! This can be the leading mock framework for c++.
Very, very good framework! We are using in your company to make our Unit Tests easier and more robust. Congratulations. Very nice work !
Thanks so much... If there are any problem, just send me email and let me fix it.
Looks cool. I have two questions: 1) How can I handle the case where delete is called on the "interface"? 2) What can I do if my abstract class has a constructor that gets arguments?
Apart from my suggestions, I love it!
Oh, Glad to know you love it...
Thanks so much:)
cant use both Expect() and Will() on the same method?? It should be working, let me check..
Any news? When I try to use both, I get the capabilities of Will(), but the verification of expected parameters does not seem to function.
Hi onfreund, i fixed that bug in current build (v0.21.1). And added Clear() method i mention before to that build. (It is Clear(), not Reset()..)
Nice framework! However, I must be missing something -- how do I get the mock objects "hooked into" a UUT? Do you have an example of this?
Hi LeSchwa?, i dont understand what you mean... You mean how is the mock objects being used in Unit-Test , or sth else???
The fix works great, and so does clear. I have a couple more suggestions (in addition to somehow handling destructor calls):
What I mean is to simply save the need for redirect in cases like your MockObjectMethodRedirectFreeFunc? test. So instead of rs = "CHANGED", in a redirection function, I would like to write: mock.Method(&IInterface::ComplexFunction).Expect<0>("First").Expect<1>("Second").Expect<2>("Third").Set<1>("CHANGED").Will("Result");
# I think that it is useful, so i will add that in the next version too, Hey, i added another page for general discussion, i think it is better. (but in fact, if google code have a forum feature...)
Nice framework. However i could not find the 'Verify' expectations support as described in the usage above. Am i missing something ?
Never mind. I was looking in the wrong place.
What a fantastic framework...
I just try some of your samples and it works well. The precompile binary save me a lot of works and it is just plug and play without any issue. It integrates well with the CxxUnit? framework I used. I really like it. I will try further test with my project. Thanks for the hard work.
Hi sgwong513:
Thank you so much, and we are working on version 0.4, which improve the usage so much, hope you will enjoy this library.
And where do you come from ?? 我是香港人..
Hi, a bug about compared with (const char).It lead to test failure in test MockObjectMethodSimpleExpect?.( My compiler is VC9). Maybe fixed as below:
comparable.h(46):
old: return any_cast<To>(other) == (To)any_cast<From>(mData) may be:
is_equal实现时,对(const char*)作特殊考虑