Home > other >  Writing testable code in c that mocks out third-party dependencies
Writing testable code in c that mocks out third-party dependencies

Time:04-21

I am trying to understand what could be the best design that helps in writing testable code. Let's consider below code ..

void Connection::Connect(const string& url)
{
    // My code here that I want to test
    ThirdpartClass::Connect(modifiedUrl)
    // My code here that I want to test
}

In above example ThirdpartClass::Connect(modifiedUrl) is a third part dependency that actually connects to some third-party server which I want to omit as a part of my unit test code and replace it with mock connect call while executing unit tests. My existing code is tightly bound with third party dependency which makes non testable without involving third party. Is there a better design that makes my code test ready.

Low latency is important so run time polymorphism should be a last resort.

I am planning to use google test framework for writing unit test code.

CodePudding user response:

You can give static polymorphism (i.e. templates) a try if you really want to, although I'm not sure the extra complication for the code will be worth it in the end.

First, make your Connection class templated on the type of the class you'll be calling for the connection:

template <typename C = ThirdPartyClass>
class Connection { ... }

Then, your Connect function now looks like this:

void Connection<C>::Connect(const string& url)
{
    // My code here that I want to test
    C::Connect(modifiedUrl)
    // My code here that I want to test
}

Whatever type you pass in as a template parameter to Connection will be used, instead of forcing you to use ThirdPartyClass.

For testing, you can then do the following:

using TestConnection = Connection<MockClass>;

And for actual code, use the ThirdPartyClass instead of the MockClass.

CodePudding user response:

You have to somehow remove the dependency to the third party class when you are testing and unfortunately, you will have to slightly modify your code.

You can create a wrapper around your third party functions. For example:

class ThirdPartyWrapperInterface {
 public:
  virtual bool Connect(std::string url) = 0;
};

// Use this in production
class ThirdPartyWrapper : public ThirdPartyWrapperInterface {
 public:
  bool Connect(std::string url) override {
   return ThirdpartClass::Connect(modifiedUrl);
  }
};

// Use this for test
class MockThirdPartyWrapper : public ThirdPartyWrapperInterface {
 public:
  MOCK_METHOD(bool, Connect, (std::string), (override));
};

Now your original code should use the wrapper instead and it can select between the two classes using dependency injection as you would normally do when you mock a function.

I understand that runtime polymorphism is not ideal, so you can use templates instead. See here or here for an example.

  • Related