Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unresolved externals when compiling unit tests for Visual C++ 2012

I want to create unit tests for a Visual C++ project. I tried following these MSDN instructions. I've found pages where they differentiate between unmanaged/mixed/pure code, but I don't fully understand those concepts. My code doesn't use .NET and would likely compile under MinGW with a few code adjustments.

My main project builds an executable, so I followed the steps under To reference exported functions from the test project. For starters I got different project options:

I went with Native Unit Test Project. I added a reference to my main project and I set Include Directories to $(SolutionDir)\Cubes;$(IncludePath). I wrote my code and got this when compiling:

1>Creating library C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.lib and object C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.exp
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Room::Room(void)" (??0Room@@QAE@XZ) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency@LayoutTest@CubesTest@@QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Layout::Layout(class Room *,int)" (??0Layout@@QAE@PAVRoom@@H@Z) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency@LayoutTest@CubesTest@@QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: void __thiscall Layout::add(int,int,class Room *)" (?add@Layout@@QAEXHHPAVRoom@@@Z) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency@LayoutTest@CubesTest@@QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: void __thiscall Layout::clear(int,int,bool)" (?clear@Layout@@QAEXHH_N@Z) referenced in function __catch$?NumOfRoomsConsistency@LayoutTest@CubesTest@@QAEXXZ$0
1>C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.dll : fatal error LNK1120: 4 unresolved externals

If I'm not mistaken, this means that the compiler finds the header files, but not the source files. What am I missing?

like image 852
Pieter Avatar asked Dec 23 '12 11:12

Pieter


1 Answers

Here is a step-by-step description on how to add an EXE as an unit-test target.

The key point is to "export" the functions/classes you want to test... You can download the complete sample here: http://blog.kalmbachnet.de/files/CPP_UnitTestApp.zip (I did not change any project settings, so all changes you can see in the source-code; of course, some parts can be made in the project settings).

  1. Create a Win32 Application (Console or MFC or Windows, does not matter); I created a console project called CPP_UnitTestApp:

  2. Add a function you want to test (you can also add classes). For example:

    int Plus1(int i)
    {
      return i+1;
    }
    
  3. Add a header file for the functions you want to test: CPP_UnitTestApp.h

  4. Put the declaration of the methods into the header file, and also export these functions!

    #pragma once
    
    #ifdef EXPORT_TEST_FUNCTIONS
    
    #define MY_CPP_UNITTESTAPP_EXPORT __declspec(dllexport)
    #else
    #define MY_CPP_UNITTESTAPP_EXPORT
    #endif
    
    MY_CPP_UNITTESTAPP_EXPORT int Plus1(int i);
    
  5. Include this header file in the main-cpp (here CPP_UnitTestApp.cpp) and define the EXPORT_TEST_FUNCTIONS before including the header:

    #define EXPORT_TEST_FUNCTIONS
    #include "CPP_UnitTestApp.h"
    
  6. Now add a new project (Native unit test project: UnitTest1)

  7. Include the header and the lib to the "unittest1.cpp" file (adopt the paths as you want):

    #include "..\CPP_UnitTestApp.h"
    #pragma comment(lib, "../Debug/CPP_UnitTestApp.lib")
    
  8. Go to the project settings of the test project add add a reference to the "UnitTest1" project (Project|Properties|Common Properties|Add New Reference...: Select under "Projects" the "CPP_UnitTestApp"-Project)

  9. Create the unit test function:

    TEST_METHOD(TestMethod1)
    {
      int res = Plus1(12);
      Assert::AreEqual(13, res);
    }
    
  10. Run your unit test ;)

As you can see, the main point was to export the function declaration! This is done via __declspec(dllexport) even if it is an EXE.

As I said, the demo project can be downloaded here: http://blog.kalmbachnet.de/files/CPP_UnitTestApp.zip

like image 119
Jochen Kalmbach Avatar answered Nov 16 '22 03:11

Jochen Kalmbach