I’m trying to create a test environment for using an external C++ API so that I can test things offline without having to be connected to the actual service. In essence, I want to create my own fake service that will be used for testing purposes. However, I want to be able to change between these two environments easily without having to change a ton of code. Basically, I want to be able to use the external C++ API classes in a test environment somehow. One problem I’m running into is that since the classes are part of an external API, I can’t change them. I can only wrap them in other classes I create. How can I deal with that while being able to create an environment that doesn’t require me changing a ton of code every time I want to switch back and forth? I have some sample code below (the relevant pieces where the API is being used). How can I put these classes below in a test harness? Thanks!
...
SessionOptions sessionOptions;
sessionOptions.setServerHost(d_host.c_str());
sessionOptions.setServerPort(d_port);
Session session(sessionOptions);
if (! session.start())
{
std::cerr <<"Failed to start session." << std::endl;
return;
}
if (! session.openService("//blp/mktdata"))
{
std::cerr <<"Failed to open //blp/mktdata" << std::endl;
return;
}
...
SubscriptionList subscriptions;
std::set<std::string>::const_iterator cItorSubscriptionStrings(m_SubscriptionStrings.begin());
for ( ; cItorSubscriptionStrings != m_SubscriptionStrings.end(); ++cItorSubscriptionStrings)
{
subscriptions.add((*cItorSubscriptionStrings).c_str(),
"LAST_PRICE,BID,ASK,TIME",
"",
CorrelationId((char*)(*cItorSubscriptionStrings).c_str()));
}
session.subscribe(subscriptions);
while (true)
{
Event event = session.nextEvent();
MessageIterator msgIter(event);
...
while (msgIter.next())
{
Message msg = msgIter.message();
if (event.eventType() == Event::SUBSCRIPTION_DATA)
{
if ((msg.hasElement("LAST_PRICE")) || ((msg.hasElement("BID")) && msg.hasElement("ASK")))
{
double mid = 0;
if ((msg.hasElement("BID")) && (msg.hasElement("ASK")))
{
mid = (msg.getElementAsFloat64("BID") + msg.getElementAsFloat64("ASK")) / 2;
}
else
{
mid = msg.getElementAsFloat64("LAST_PRICE");
}
...
}
}
}
...
}
One thing you can do is to use the interface (i.e. the header files) and provide an implementation of your own, at least for those functions you care about. To switch between both versions essentially amounts to linking with different libraries: yours for testing, theirs for the real implementation.
There are a few issues with that which can be addressed e.g. by only retaining the public interface and changing the private interface (on this case compilation needs to be directed at the different declarations, e.g. using different search pathes for the headers):