I am working on a legacy project that makes massive use of ATL COM objects. The task is to extend the unit testing (googletest) by the capability of mocking COM objects, or the smart pointers accessing them. To illustrate, I created a small example project with a single ATL simple object, which only exports the method methodB (part of idl file):
object,
uuid(070a4996-d9cf-4434-a823-3ea9043de394),
dual,
nonextensible,
pointer_default(unique)
]
interface IMyATLObj : IDispatch
{
[id(1)] HRESULT methodB([in] SHORT in, [out, retval] SHORT *out);
};
The objects are accessed using smart pointers of base type _com_ptr_t, such as in this example:
#include <comdef.h>
#include ".../ATLExample_i.h"
_COM_SMARTPTR_TYPEDEF(IMyATLObj, __uuidof(IMyATLObj));
IMyATLObjPtr create() {
IMyATLObjPtr objPtr;
objPtr.CreateInstance(__uuidof(MyATLObj));
return objPtr;
}
void use(IMyATLObjPtr objPtr) {
short val = 0;
objPtr->methodB(1, &val);
std::cout << val << std::endl;
}
Now the question is how I can test the function use(...) without actually creating a COM object. Of course I can create a wrapper class as a facade to all COM interactions that I can mock as usual, e.g.:
class MyObjFacade {
public:
MyObjFacade() {
objPtr.CreateInstance(__uuidof(MyATLObj));
}
virtual short methodB(short in) {
short val;
if (objPtr->methodB(in, &val) == S_OK)
return val;
else
throw;
}
IMyATLObjPtr objPtr;
};
class MYObjMock : public MyObjFacade {
public:
MOCK_METHOD1(methodB, short(short in));
};
void use(MyObjFacade *objPtr) {
short val = 0;
val = objPtr->methodB(1);
std::cout << val << std::endl << std::flush;
}
TEST_F(COMMockTest, Test1) {
MYObjMock mock;
EXPECT_CALL(mock, methodB(_)).WillOnce(Return(43));
use(&mock);
}
But that would obviously leave me with lots of boiler plate code and (possibly) unnessessary changes - this solution would probably not be well adopted. I am looking for an elegant solution that, for example, either introduces a mock object into IMyATLObjPtr mocks the pointer object itself. However, I don't really know where to start because all the available interfaces are generated by ATL and are not easily accessible.
Any ideas?
Related
I am new to google test environment. I have a sample code written in C and want to perform unit test with Google test framework.
Below is the sample code
// My module function (test.c)
void Update_user_value(void)
{
int user_value;
user_value = get_val_module(); /* return a integer value*/
if(user_value == 0x1)
update_user_flag(true);
else
update_user_flag(false);
}
// This function is in the other module(stub.c) , so we can use Mock function
void update_user_flag(bool val)
{
struct *temp;
if(val == true)
{
temp->userflag = 1;
}
else
{
temp->userflag = 0;
}
}
I wan to write a test case for the Update_user_value function (only for test.c). Through this function, i am sending some flag value to other module (update_user_flag) to set the flag.
I have written a simple google test like this
TEST_F(sampletest, setuser_flag_true_testcase)
{
//Get value from module
ON_CALL(*ptr1, get_val_module()).WillByDefault(Return(0x1)); //Mock function
EXPECT_CALL(*ptr2, get_val_module(_)).Times(1); // Mock function
Update_user_value();
}
TEST_F(sampletest, setuser_flag_false_testcase)
{
//Get value from module
ON_CALL(*ptr1, get_val_module()).WillByDefault(Return(0x0)); //Mock function
EXPECT_CALL(*ptr2, get_val_module(_)).Times(1); // Mock function
Update_user_value();
}
My question: Is this test case is enough to validate the Update_user_value function ?
Also i want to know, EXPECT_CALL() is good to use for setting a value to other module ?
If my understanding is wrong, please suggest me a better test case ?
ON_CALL, EXPECT_CALL are macros designed to be used on mock objects. Usually the use case is as follows:
You create an interface to derive from (it will be mocked in your test).
You pass the mock object (to method or via dependency injection).
You make expectations on this object.
See example:
class Foo {
public:
virtual ~Foo() = default;
virtual int bar() = 0;
};
class FooMock : public Foo {
public:
MOCK_METHOD0(bar, int());
};
bool check_bar_over_42(Foo& foo) {
if (foo.bar() > 42) {
return true;
}
return false;
}
TEST(check_bar_over_42_test, bar_below_42) {
FooMock fooMock{};
EXPECT_CALL(fooMock, bar()).WillOnce(testing::Return(41));
ASSERT_FALSE(check_bar_over_42(fooMock));
}
TEST(check_bar_over_42_test, bar_above_42) {
FooMock fooMock{};
EXPECT_CALL(fooMock, bar()).WillOnce(testing::Return(43));
ASSERT_TRUE(check_bar_over_42(fooMock));
}
AFAIK there is no way of using EXPECT_CALLs on C-like functions. One approach for your problem would be link-time mocking: given a method get_val_module is defined in a separate library, you can create test-only library with get_val_module that will allow you to return the expected values. In tests you would link against test lib, in production - against the real lib.
In below code snippet I do require to instantiate the object through factory method in order to call the selected adapter (i.e. adapterTwovalue)but while calling through factory method i am not able to get the desire results. When we assign static declared object's address (i.e adapter = &at) it works but with factory i usually get the blank output.
I tried as well with (adapter = new adapterTwo()) to instantiate the object but output string is giving blank results. As per my requirement i need to populate the all the getters in connect function which is pure virtual function to frame the response.Anybody can suggest how to achieve this using factory method.
#include <iostream>
using namespace std;
class IAdapter
{
public:
enum FactoryList { AdapterOnevalue = 0, AdapterTwovalue };
virtual void connect() = 0;
static IAdapter* CreateList(FactoryList);
virtual ~IAdapter() {}
};
class LibraryOne
{
string property;
public:
void SetConnection(string property)
{
this->property = property;
}
string getConnection()const
{
return property;
}
};
//LibraryTwo
class LibraryTwo
{
string broker;
public:
void SetBroker(string broker1)
{
this->broker = broker1;
}
string getBroker() const
{
return broker;
}
};
//adapterOne
class AdapterOne : public IAdapter
{
LibraryOne one;
string constring;
public:
void SetClientconnection(string constring)
{
one.SetConnection(constring);
}
string GetClientconnection()
{
return one.getConnection();
}
void connect()
{
constring = GetClientconnection();
}
};
//Adapter to use library two
class AdapterTwo : public IAdapter
{
LibraryTwo two;
string brokerstring;
public:
void SetClientbroker(string constring)
{
two.SetBroker(constring);
}
string GetClientbroker()
{
return two.getBroker();
}
void connect()
{
string constring = GetClientbroker();
cout << "final value=" << constring;
}
};
IAdapter* IAdapter::CreateList(FactoryList SelectList)
{
IAdapter *ListObject;
switch (SelectList)
{
case AdapterOnevalue:
ListObject = new AdapterOne();
break;
case AdapterTwovalue:
ListObject = new AdapterTwo();
break;
default:
ListObject = NULL;
}
return ListObject;
}
int main()
{
IAdapter *adapter = 0;
//LibraryTwo obj;
AdapterTwo at;
at.SetClientbroker("amqp");
//cout << at.GetClientbroker();
//adapter = &at; it works
adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);//it doesn't work
//Just do the operation now
adapter->connect();
return 0;
}
You can see the complete solution in below share link.
http://coliru.stacked-crooked.com/a/d8b9d32a1fa989c9
Here is the explanation.
(1) setClientBroker() or all other adapters related setter functionality needs to be implement as a virtual function in Interface with default parameter value " " (blank string).
(2) you need to always use override keyword (c++11) feature in derive class for setters so that compiler will cross check during compilation whether proper virtual method is being overridden or not.
(3) instead of using local raw pointer , always use smart pointer . below is the
implementation link for the same.
http://coliru.stacked-crooked.com/a/2feea991ee90d4a2
With your code I expect the output: final value=.
It will not print final value=amqp cause you need to call SetClientbroker("amqp") on the right adapter object (adapter in your example).
Anyway, I would think about putting a virtual method SetString in the base class, so you could simply do:
int main()
{
IAdapter *adapter = 0;
//LibraryTwo obj;
//AdapterTwo at;
//at.SetClientbroker("amqp");
//cout << at.GetClientbroker();
//adapter = &at; it works
adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);//it doesn't work
//Just do the operation now
adapter->SetString("amqp");//<---------
adapter->connect();
return 0;
}
EDIT after the comment:
You need to cast the object, at this point (as suggested by #Aconcagua).
But IMHO it's not elegant at all. I think you are going to loose the benefits gained with the factory method.
IAdapter* adapter = nullptr;
AdapterTwo at;
adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);
You have created two independent objects here (as calling new within createList): at and the one adapter points to.
AdapterTwo at;
at.SetClientbroker("amqp");
Now sure you get the expected output if you let adapter point to at, but how could the other object be aware of the string you set in the first one?
adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);
adapter->SetClientbroker("amqp"); // (*) !!!
You need to set the broker at the other object, too. As being different objects, you even can set the brokers independently:
AdapterTwo at;
at.SetClientbroker("amqp");
IAdapter* adapter = IAdapter::CreateList(IAdapter::AdapterTwovalue);
adapter->SetClientbroker("aconcagua"); // (*) !!!
Output now would be (if you called connect on both objects):
final value=amqp
final value=aconcagua
Only: The marked lines ((*)) won't compile as your base class does not provide the appropriate setter!
There are now different solutions for this problem. You could, for instance, just cast the object:
// if you are REALLY 100% sure the object is of appropriate type:
static_cast<AdapterTwo*>(adapter)->setClientBroker("...");
// if NOT:
AdapterTwo* a2 = dynamic_cast<AdapterTwo*>(adapter);
if(a2)
a2->setClientBroker("...");
else
// appropriate error handling
You could find a more generic name for the set/get Broker/ClientConnection functions, have them already pure virtual within IAdapter and override them in the two implementing adapter classes, so you could then just call adapter->setXYZ("ampq");. [Edit: according to your comment to the question, not an option in the given case]
My personal favourite is providing an additional parameter to your createList function such that the setter would already be called within the factory - possibly with appropriate default: empty string, if you opt for a std::string parameter, or nullptr in case of char const*. You'd only call the setter if the parameter is not matching the default, of course... Alternatively, you could have two overloads.
I am trying to do a unit test to test the DoLogin method:
CLoginActivity::CLoginActivity()
{
m_pTask = new Task();
}
void CLoginActivity::DoLogin()
{
m_pTask.execute();
}
where the Task is another class that I need to mock.
class MockTask : public Task
{
public:
MOCK_METHOD0(Execute, void());
};
To inject the MockTask task object, I must change my construction:
CLoginActivity::CLoginActivity(Task& task)
{
m_pTask = task;
}
or write a set function:
CLoginActivity::SetTask(Task& task)
{
m_pTask = task;
}
Is there other method to inject instead those two methods? And I use gmock in my unit test project.
Injecting via constructor is the best - keep this design.
But there are few others ways for people that like to complicate simple things.
1) Make your CLoginActivity class template:
template <class TaskImpl>
class CLoginActivityTemplate
{
CLoginActivityTemplate() { m_pTask = new TaskImpl(); }
};
using CLoginActivity = CLoginActivityTemplate<Task>;
In your tests, test this instantion:
using CLoginActivityTestable = CLoginActivityTemplate<TaskMock>;
However it is not always so easy - because it is often hard to get access to this mock to set expentantions on it. But you might define TestMockWrapper class
to ensure access to mock task is easy:
class TestMockWrapper : public TestMock
{
public:
static TestMock* lastCreated;
TestMockWrapper() { lastCreated = this; }
};
using CLoginActivityTestable = CLoginActivityTemplate<TaskMockWrapper>;
2) Inject factory object to your constructor:
CLoginActivity::CLoginActivity(ITaskFactory& taskFactory)
{
m_pTask = taskFactory.create();
}
You need to mock this factory class to ensure mock-factory creates mock-object. Maybe it does not look promissing - but this is just intro to next point.
3) Have special factory function implemented in other file:
CLoginActivity.cpp
#include "TaskCreate.hpp"
CLoginActivity::CLoginActivity()
{
m_pTask = taskCreate();
}
TaskCreate.cpp
// your "real" function here
ITask* createTask() { return new Task(); }
Having such design- create UT test for your CLoginActivity with using only selected files from your projects - simple speaking - replace TaskCreate.cpp with TaskcreateStub.cpp in your UT project:
CloginActivity.cpp
TaskMock.cpp (if exists)
TaskCreateStub.cpp
TaskCreateStub.cpp should return task-mock - not real task. You need also access to this returned mock-object - so you can set expectations on it.
TaskCreateStub.cpp
// your "real" function here
static TaskMock* taskMockForCreateStub = nullptr;
ITask* createTask() { return taskMockForCreateStub ; }
void setTaskMockForCreateTaskStub(TaskMock* taskMock) { taskMockForCreateStub = taskMock; }
I strongly discourage you from using such linker-level mocking. Use it only for testing legacy code where you cannot redesign it and this might be the only way for using mock...
I want to test makeTvSeries() method without extracting getNumberOfShows, printMsg to other class and then mocking it so I thougth about mocking TvChannel class.
Is it possible to call base class method (makeTvSeries) which will call child methods: getNumberOfShows, printMsg without getting rid of virtuality? So I could use same mock class definiton in other tests for instance foo.playTvSeries(mockTvChannel) and expect calls to makeTvSeries?.
Moreover is it good practice what I am doing at all? In whole program there are also other classes which use cin and cout and as I said at the begining I didn't wanted to extract all of them to one class responsible for input/output. What are Yours experiences and what I should do ?
class MockTvChannel : public TvChannel{
public:
MOCK_METHOD0(getNumberOfShows, int());
//MOCK_METHOD0(makeTvSeries, void());
MOCK_METHOD0(printMsg, void());
};
TEST(sample_test_case, sample_test)
{
MockTvChannel channel;
EXPECT_CALL(channel, getNumberOfShows())
.Times(1)
.WillOnce(::testing::Return(10));
EXPECT_CALL(channel, printMsg())
.Times(10);
channel.makeTvSeries();
}
class TvChannel
{
protected:
virtual int getNumberOfShows(){
int nShows;
std::cin >> nShows;
return nShows;
}
virtual void printMsg(){
std::cout << "What a show!" << std::endl;
}
public:
/*virtual*/ void makeTvSeries()
{
int nShows = getNumberOfShows();
for(int i = 0; i<nShows; ++i){
printMsg();
}
}
virtual ~TvChannel() {};
};
So I could use same mock class definiton in other tests for instance foo.playTvSeries(mockTvChannel) and expect calls to makeTvSeries?
Yes, you can. And your implementation is fine.
is it good practice what I am doing at all?
It is. Following the SOLID principle, you applied next principles :
LSP : in unit test you switched real implementation and tested using mock, so your makeTvSerier works
ISP : your class has an interface
DIP : I guess, you want to use inversion of control when you pass instance of mock to other objects
The latest version of Hippo Mocks (in its Git repository) looks to have added support for COM interfaces. I've tried mocking an ADO connection object; which took some tweaking of Hippo Mocks to build properly (seems the COM version of the code wasn't updated for changes in the rest of Hippo Mocks). I have it building now, but the following test fails:
MockRepository mocks;
auto pConn = mocks.Mock<ADONS::_Connection>();
mocks.OnCall(pConn, ADONS::_Connection::AddRef).Return(1);
ADONS::_ConnectionPtr conn = pConn;
The very first thing the smart pointer does is AddRef the interface. My mock shouldn't care about reference counting, so I add a call expectation that simply returns 1. However, as soon as AddRef gets called, a HippoMocks::NotImplementedException gets thrown.
Has anyone had success with mocking a COM interface with Hippo Mocks?
I had the same issue and solved it.
The actual version of hippomocks is now published on github:
https://github.com/dascandy/hippomocks
Great appreciation for the provided links, which helped to find an idea for the fix.
UPDATE, Details about my implementation and the added COM support.
First I made it work, which the following test demonstrates
class ICom
{
public:
virtual ~ICom() {}
virtual long __stdcall A(void) = 0;
virtual long __stdcall B(int) = 0;
virtual long __stdcall C(int, int) = 0;
...
};
TEST(checkStdCallBase)
{
MockRepository mocks;
ICom* ic = mocks.Mock<ICom>();
mocks.ExpectCall(ic, ICom::A)
.Return(1);
long actual = ic->A();
EQUALS(1, actual);
}
In order to make it work I had to patch several places in hippomocks.h, the most vital in virtual_function_index method. The correction ensures correct address calculation for the call on an interface.
Second, I added some common setup helpers for COM objects, providing standard behaviour for AddRef, Release and QueryInterface.
The tests show how to use it:
MIDL_INTERFACE("4745C05E-23E6-4c6d-B9F2-E483359A8B89")
COMInterface1 : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE getTObjectCount(
/* [out] */ unsigned long *pCount) = 0;
};
typedef GUID ESTypeID;
MIDL_INTERFACE("356D44D9-980A-4149-A586-C5CB8B191437")
COMInterface2 : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE getMappablePackages(
/* [out] */ long *pSize,
/* [size_is][size_is][out] */ ESTypeID **pIdList) = 0;
};
TEST(CheckThat_AddCommExpectations_Stubs_QueryInterface_AddRef_Release)
{
MockRepository mocks;
COMInterface1* deviceMock = mocks.Mock<COMInterface1>();
AddComExpectations(mocks, deviceMock);
{
CComPtr<IUnknown> pUnk = deviceMock;
CComQIPtr<COMInterface1> pDevice = pUnk;
CHECK(pDevice == pUnk);
IUnknown* p = NULL;
pDevice->QueryInterface(__uuidof(IUnknown), (void**)&p);
CHECK(p == deviceMock);
}
}
TEST(CheckThat_ConnectComInterfaces_Stubs_QueryInterface_ToEachOther)
{
MockRepository mocks;
COMInterface1* deviceMock = mocks.Mock<COMInterface1>();
COMInterface2* devMappingMock = mocks.Mock<COMInterface2>();
ConnectComInterfaces(mocks, deviceMock, devMappingMock);
{
//Com objects can reach each other
CComQIPtr<COMInterface2> pDevMapping = deviceMock;
CHECK(pDevMapping != NULL);
CHECK(pDevMapping == devMappingMock);
CComQIPtr<COMInterface1> pDevNavigate = devMappingMock;
CHECK(pDevNavigate != NULL);
CHECK(pDevNavigate == deviceMock);
}
}
The helper methods AddComExpectations and ConnectComInterfaces are provided in a separate header "comsupport.h". The header is an add-on for Hippomocks:
template <typename T>
void AddComExpectations(HM_NS MockRepository& mocks, T* m)
{
mocks.OnCall(m, T::AddRef)
.Return(1);
mocks.OnCall(m, T::Release)
.Return(1);
mocks.OnCall(m, T::QueryInterface)
.With(__uuidof(T), Out((void**)m))
.Return(S_OK);
mocks.OnCall(m, T::QueryInterface)
.With(__uuidof(IUnknown), Out((void**)m))
.Return(S_OK);
}
template <typename T1, typename T2>
void ConnectComInterfaces(HM_NS MockRepository& mocks, T1* m1, T2* m2)
{
//from T1 to T2
mocks.OnCall(m1, T1::QueryInterface)
.With(__uuidof(T2), Out((void**)m2))
.Return(S_OK);
//from T2 to T1
mocks.OnCall(m2, T2::QueryInterface)
.With(__uuidof(T1), Out((void**)m1))
.Return(S_OK);
AddComExpectations(mocks, m1);
AddComExpectations(mocks, m2);
//no support for interface hierarchies
//no Base IUnknown -> do it yourself if you really need that special case
}