Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++/CLI

How to use NUnit to test native C++ code

3.00/5 (8 votes)
18 Jan 2010CPOL3 min read 1   575  
Because NUnit is designed to unit test managed code, it does not lend itself to test unmanaged C++ code as easily as for C#, until now!

Introduction

There are several ways to test native (unmanaged) C++ code using NUnit. Because NUnit is designed to unit test managed code, it does not lend itself to test unmanaged C++ code as easily as for C#. Until now.

Background

When testing C# code, in most cases, no changes have to be made to the code before it can be tested with NUnit. That is, as long as the C# code is accessible via a public interface to a DLL, nothing more needs to be done in order to access the code from an NUnit test DLL. The developer creates the NUnit test DLL and calls the code under test.

With C++, however, additional steps need to be taken. For example:

  • Expose the C++ class as a CoClass so that it can be instantiated using COM.
  • or

  • Recompile the component as Managed C++ (C++/CLI).

In addition to the extra work which is not required for a C# component, these options have their own drawbacks. In the first case, unless the C++ class was already designed this way, it will likely be non-trivial to convert a C++ class to be accessible through COM. In the second case, if the C++ class is in a native code module, an extra step is needed to recompile it as managed code just for testing, ensuring the development tool supports this (VC6 doesn't), and the code needs to be modified to expose the class as a managed class, among other issues.

Proposal

The proposal is to use a seldom used feature in C++, which is to export the native C++ class under test from the DLL, then use the C++ Interop (implicit P/Invoke) feature to call the class from the test DLL, which is written in C++/CLI.

The advantage of this solution is that it does not require a special version of the production DLL to be created just for testing. We still need to export the C++ class, but that's no different than if the production class was a private C# class. NUnit won't be able call that either, so this is a general issue with NUnit in that code under test has to be externally accessible. Furthermore, it's also assumed that the code under test is in a DLL, which is what we would have to do with C# code.

C++'isms

In C#, the only way to reuse code is to put that code in a DLL. C++, however, also lets us create static link libraries (traditional .lib), and also code can be shared by simply #include'ing it. The solution described in this article does not address testing code in a static link library or shared C++ header files.

Solution details

Let's say that you have a C++ DLL that has the following class that you want to test:

C++
class CChecksum
{
public:
    DWORD GetChecksum( LPBYTE buf, LONG len );
};

The first step is to export the class so that it can be called from outside the DLL. Add __declspec(dllexport) after the class keyword, so the resulting code looks like this:

C++
class __declspec(dllexport) CChecksum
{
public:
    DWORD GetChecksum( LPBYTE buf, LONG len );
};

Next, create the NUnit test DLL in C++/CLI. It may look like this:

MC++
using namespace NUnit::Framework;
...
[TestFixture]
public ref class CChecksumTester
{
public:
    [Test]
    void GetChecksumTest()
    {
        char* buf = "This is a test";
        CChecksum c;
        DWORD v = c.GetChecksum( (LPBYTE)buf, strlen(buf) );
        Assert::AreEqual(v,552367893);
    }
};

You can now load this the test DLL from NUnit. You'll have to do the usual C++ things necessary to call a DLL, such as have the test DLL link to the implicit library (.lib) of the DLL being tested, and the test code needs to #include the header file of the class.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)