I am having a problem with Visual Studio 2019 CPPUnitTestFramework. I follow the instructions, but every time I get an error. I have looked for tutorials, but anything I get is for Visual Studio 2017 and it does not solve my problem.
I am writing a program that uses OOP in C++ and I want to make unit tests, since it is going to be a considerably long project. The problem that I am having is that the program is not compiling in the test module.
Consider that I have the code such that I have the header file:
//A.h
#pragma once
class A
{
private:
// One parameter.
int a;
public:
// Add function.
int add(int, int);
// Subtract function.
int subtract(int, int);
A();
};
with the proper source file:
// A.cpp
#include "A.h"
int a;
int A::add(int alpha, int beta)
{
return alpha + beta;
}
int A::subtract(int alpha, int beta)
{
return alpha - beta;
}
A::A()
{
a = 4;
}
The structure of the program looks something like this:
To make my Unit Test, I right click on the "Solution 'TestTestUnit'" label and choose new project, look for the unit test, add the unit test and attach the reference, such that I get a file structure such as the one below:
To perform the unit test I write the code:
// TestUnitForTestTestUnit.cpp
#include "pch.h"
#include "CppUnitTest.h"
#include "../TestTestUnit/A.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace TestUnitForTestTestUnit
{
TEST_CLASS(TestUnitForTestTestUnit)
{
public:
TEST_METHOD(TestMethod1)
{
A first;
Assert::AreEqual(first.add(3, 2), 5);
}
};
}
When I try to run a test, the Test Explorer does nothing and throws the message: Aborting test run due to build failures. Please see the build for more details.
I cannot find the mistake here. The program runs perfect, but when instantiating a new "A" object the test fails. I am stuck here, are there any suggestions? What am I doing wrong (besides developing in Windows)?
UPDATE:
I have followed the suggestion to remove the namespace, as suggested by #ChrisMM, so that the test file now reads:
// TestUnitForTestTestUnit.cpp
#include "pch.h"
#include "CppUnitTest.h"
#include "../TestTestUnit/A.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
TEST_CLASS(TestUnitForTestTestUnit)
{
public:
TEST_METHOD(TestMethod1)
{
A first;
Assert::AreEqual(first.add(3, 2), 5);
}
};
such that when I run the Test Explorer gives the same message:
with error message:
1>------ Build started: Project: TestUnitForTestTestUnit, Configuration: Debug Win32 ------
1> Creating library C:\Users\<user>\Desktop\CPlusPlus\TestTestUnit\Debug\TestUnitForTestTestUnit.lib and object C:\Users\<user>\Desktop\CPlusPlus\TestTestUnit\Debug\TestUnitForTestTestUnit.exp
1>TestUnitForTestTestUnit.obj : error LNK2019: unresolved external symbol "public: int __thiscall A::add(int,int)" (?add#A##QAEHHH#Z) referenced in function "public: void __thiscall TestUnitForTestTestUnit::TestMethod1(void)" (?TestMethod1#TestUnitForTestTestUnit##QAEXXZ)
1>TestUnitForTestTestUnit.obj : error LNK2019: unresolved external symbol "public: __thiscall A::A(void)" (??0A##QAE#XZ) referenced in function "public: void __thiscall TestUnitForTestTestUnit::TestMethod1(void)" (?TestMethod1#TestUnitForTestTestUnit##QAEXXZ)
1>C:\Users\<user>\Desktop\CPlusPlus\TestTestUnit\Debug\TestUnitForTestTestUnit.dll : fatal error LNK1120: 2 unresolved externals
1>Done building project "TestUnitForTestTestUnit.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
Help would be appreciated.
You cannot put a test class inside a namespace. From the documentation
TEST_CLASS must be declared at namespace scope.
I suggest you to check if TestUnitForTestTestUnit has added Additional Dependencies. When I didn’t add it, the same problem as you occurred. After I added it, the program worked fine.
Right click TestUnitForTestTestUnit->Properties->C/C++->Linker->Input->Additional Dependencies-> add ..\TestTestUnit\Debug\*.obj
Related
I just started a small console app in VS2019 and added a Google Test project. The program itself compiles and runs fine, however, if I move function code from the header to the cpp-file, I get the LNK2019 and LNK1120 errors:
Severity
Code
Description
Project
File
Line
Error
LNK2019
unresolved external symbol "public: void __cdecl MyClass::someFunction(void)" (?someFunction#MyClass##QEAAXXZ) referenced in function "private: virtual void __cdecl MyTests_basicTest_Test::TestBody(void)" (?TestBody#MyTests_basicTest_Test##EEAAXXZ)
Tests
Tests.obj
1
Error
LNK1120
1 unresolved externals
Tests
Tests.exe
1
MyClass.h:
#pragma once
class MyClass
{
public:
void someFunction();
};
MyClass.cpp:
#include "MyClass.h"
void MyClass::someFunction() {
// do something
}
Main.cpp:
#include "MyClass.h"
int main()
{
MyClass mc;
mc.someFunction();
}
Tests.cpp:
#include "pch.h"
#include "../TestApp/MyClass.h"
TEST(MyTests, basicTest) {
MyClass mc;
mc.someFunction();
EXPECT_EQ(1, 1);
}
I could just put all of the code in the header file of course, but I don't think that is what I'm supposed to do, so I would greatly appreciate some help on this.
Edit:
I feel like I'm one step closer (though it is only a shot in the dark): I added the directory that contains all the *.obj files under [Tests Project] -> "Properties" -> "Configuration Properties" -> "Linker" -> "Input" -> "Additional Dependencies": D:\Application\x64\Debug
However, now I get the following error:
LNK1104 cannot open file 'D:\Application\x64\Debug.obj'
And indeed, the directory contains all kinds of obj-files but not Debug.obj. :/
Edit 2:
Solved! I followed this link under "To link the tests to the object or library files". Important that you really just enter the base name of the file itself without the ".obj".
I'm trying to perform some basic unit tests on a class that's in one project in a solution (Let's call it Project1) in another unit test project (Let's call it UnitTest1) in c++. I'm using the very latest version of visual studio 2019.
I created a brand new solution in visual studio 2019 for c++, and added a console application with a class HelloWorld in another file that just has a method to return a std::string "Hello World".
I then added a new "Native Unit Test Project" to the solution, under references added the Project1 console application, and typed the code as shown below:
The project1 file:
#include <iostream>
#include "HelloWorld.h"
int main() {
HelloWorld* hello = new HelloWorld();
std::cout << hello->sayHello();
}
HelloWorld.h:
#pragma once
#include <string>
class HelloWorld {
public: HelloWorld();
public: std::string sayHello();
};
HelloWorld.cpp:
#include "HelloWorld.h"
#include <string>
HelloWorld::HelloWorld() {
}
std::string HelloWorld::sayHello() {
return std::string("Hello World");
}
UnitTest1.cpp:
#include "pch.h"
#include "CppUnitTest.h"
#include "..//ConsoleApplication1/HelloWorld.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest1 {
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
HelloWorld* hello = new HelloWorld();
Assert::AreEqual(hello->sayHello(), std::string("Hello World"));
}
};
}
When i try to run the test via the test explorer, i get:
1>------ Build started: Project: UnitTest1, Configuration: Debug Win32 ------
1>pch.cpp
1>UnitTest1.cpp
1> Creating library C:\Users\Iblob\source\repos\ConsoleApplication1\Debug\UnitTest1.lib and object C:\Users\Iblob\source\repos\ConsoleApplication1\Debug\UnitTest1.exp
1>UnitTest1.obj : error LNK2019: unresolved external symbol "public: __thiscall HelloWorld::HelloWorld(void)" (??0HelloWorld##QAE#XZ) referenced in function "public: void __thiscall UnitTest1::UnitTest1::TestMethod1(void)" (?TestMethod1#UnitTest1#1#QAEXXZ)
1>UnitTest1.obj : error LNK2019: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall HelloWorld::sayHello(void)" (?sayHello#HelloWorld##QAE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) referenced in function "public: void __thiscall UnitTest1::UnitTest1::TestMethod1(void)" (?TestMethod1#UnitTest1#1#QAEXXZ)
1>C:\Users\Iblob\source\repos\ConsoleApplication1\Debug\UnitTest1.dll : fatal error LNK1120: 2 unresolved externals
1>Done building project "UnitTest1.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
I would have hoped that the linker should be able to find the files referenced according to microsofts own tutorial on this: https://learn.microsoft.com/en-us/visualstudio/test/writing-unit-tests-for-c-cpp?view=vs-2019
I've tried adding the classes header and cpp as an existing item to my unit test project, but then it just tries to find #include "pch.h" in the HelloWorld class when i try to run the tests.
What am i missing here to tell linker where to find the classes symbols?
Adding #include "..//ConsoleApplication1/HelloWorld.cpp" to my unitTest1.cpp file seems to have fixed things, although i'm not sure if this is an ideal solution, still, will mark as answer.
I seem to have some issues with creating new files for my project.
The issue is that in my sk_error.h file it seems to complain about unresolved external symbols (full error report below). When I place my OutOfRange class in my sk_interface.h file no one complains but when I put the class in the errors file it has issues with it.
If I was to comment out OutOfRange it works perfectly fine so I dont think that it is an issue with the DLL setup.
sk_error.h
#include <sk_platform.h>
#include <sk_interface.h>
namespace sky {
class SK_API OutOfRange : IError {
public:
OutOfRange() {
m_message = " Out Of Range";
m_value = (0 << 1);
}
std::string getMessage() override {
return m_message;
}
};
}
sk_platform.h
#if defined (SK_NONCLIENT_BUILD)
#ifndef SK_API
#define SK_API __declspec(dllexport)
#endif
#else
#ifndef SK_API
#define SK_API __declspec(dllimport)
#endif
#endif
sk_interface.h
#include <sk_platform.h>
#include <string>
namespace sky {
...
class SK_API IError {
public:
virtual std::string getMessage() = 0;
protected:
uint32_t m_value = 0;
std::string m_message = "Error not initialized";
};
}
The Client Project using the DLL
#include <sk_logmanager.h>
#include <sk_error.h>
#include <iostream>
int main() {
sky::g_LogManager.startup();
sky::OutOfRange err;
std::cout << err.getMessage() << "\n";
sky::g_LogManager.shutdown();
while (1) {}
}
Error Output
1>------ Build started: Project: SkyTest, Configuration: Debug Win32 ------
1>main.cpp
1>main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall sky::OutOfRange::OutOfRange(void)" (__imp_??0OutOfRange#sky##QAE#XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall sky::OutOfRange::getMessage(void)" (__imp_?getMessage#OutOfRange#sky##UAE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall sky::OutOfRange::~OutOfRange(void)" (__imp_??1OutOfRange#sky##QAE#XZ) referenced in function _main
1>C:\Users\Matt\Documents\Game Development\DevEnv\SkyTest\Debug\SkyTest.exe : fatal error LNK1120: 3 unresolved externals
1>Done building project "SkyTest.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Edit:
I am using Visual Studio 2017 (could be the source of the error). The Client Project is using the .lib file.
An unresolved external is always a link error. It even has it in its name: LNK2019.
It is telling you it cannot find the implementation for sky::OutOfRange::OutOfRange()
You have it in a header somewhere and you've called it, but you have not linked to the library that implements it.
We have no way of telling you what library implements it or where it lives on your hard drive. You will have to consult the documentation for OutOfRange, the author of it, or yourself.
I can tell you that you will want to check:
right click the executable project->
properties->linker->general->additional library directories
properties->linker->input->additional dependencies
and make sure the path to the library that defines OutOfRange is in the former and the library name is in the latter.
EDIT: If the library itself has a header that imports it, as it appears from the code you posted, you just need to set up the additional directories part.
In the end, you have to consult the documentation for whatever library you are using or hit up their forums.
I am not sure but this may be related to your solution configuration and solution platform. It wasn't working for me, when I set my solution configuration to "Debug" and platform to "x64"; it started working after setting it to Release - x86
I am trying to compile a very simple CMake project using Visual Studio 2013, however I am getting the following error upon trying to compile it:
error LNK1120: 1 unresolved externals cmake_issue\build\Debug\cmake_issue.exe 1 1 cmake_issue
error LNK2001: unresolved external symbol "public: static int Other::value" (?value#Other##2HA) cmake_issue\build\test.obj cmake_issue
I have a base directory with the following CMakeLists.txt in:
project(cmake_issue)
add_subdirectory(other)
add_executable(cmake_issue src/test.cc)
target_link_libraries(cmake_issue other)
And the contents of src/test.cc:
#include <cstdio>
#include "other/other.h"
int main(int argc, char *argv[]) {
printf("value = %d\n", Other::value);
return 0;
}
And a subdirectory called other with the following CMakeLists.txt in:
add_library(other SHARED src/other.cc)
target_include_directories(other PUBLIC include)
target_link_libraries(other)
And the contents of other/include/other/other.h:
#ifndef _OTHER_H_
#define _OTHER_H_
class __declspec(dllexport) Other {
public:
static int value;
};
#endif
And the contents of other/src/other.cc:
#include "other/other.h"
int Other::value = 30;
If I build the project with cmake and then open the generated sln in Visual Studio, both of the projects appear in the Solution Explorer.
If I right click and build other, it builds fine. However if I try and build cmake_issue, I get the errors above. It looks like the cmake_issue solution is not using the other.dll (or other.lib) files being generated when compiling the other solution.
I can upload a zip of the source if it is needed.
Okay, the problem is not on CMake side, but with C++. When you used dllexport'ed class in your executable, its definintion should read class __declspec(dllimport) Other. This code works fine, for example:
#include <cstdio>
class __declspec(dllimport) Other {
public:
static int value;
int a();
};
int main(int argc, char *argv[]) {
printf("value = %d\n", Other::value);
return 0;
}
Here's a link with complete solution: https://social.msdn.microsoft.com/Forums/en-US/6c43599d-6d9d-4709-abf5-4d1e3f5e4fc9/exporting-static-class-members
New to c++ and trying to test a dll but keep getting
warning C4273: 'CRootFinder::SquareRoot' : inconsistent dll linkage
RootFinder.h
#ifdef MY_EXPORTS
#define API _declspec(dllexport)
#else
#define API _declspec(dllimport)
#endif
class API CRootFinder {
public:
CRootFinder(void);
double SquareRoot(double v);
};
RootFinder.cpp
#include "stdafx.h"
#include "RootFinder.h"
double CRootFinder::SquareRoot(double v)
{
return 0.0;
}
Builds but gets warning above.
Added reference to dll to unit test project
unittest1.cpp
#include "stdafx.h"
#include "CppUnitTest.h"
#include "../c source/RootFinder.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace Tests
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
CRootFinder rooter;
Assert::AreEqual(
// Expected value:
0.0,
// Actual value:
rooter.SquareRoot(0.0),
// Tolerance:
0.01,
// Message:
L"Basic test failed",
// Line number - used if there is no PDB file:
LINE_INFO());
}
};
}
Won't build
Error 2 error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall
CRootFinder::CRootFinder(void)" (__imp_??0CRootFinder##QAE#XZ)
referenced in function "public: void __thiscall
Tests::UnitTest1::TestMethod1(void)"
(?TestMethod1#UnitTest1#Tests##QAEXXZ)
Compile dll with MY_EXPORTS preprocessor marco. Add use it in test without MY_EXPORTS definition macro.
In Visual Studio you can do that: Project right click->Propertis->C/C++->Preprocessor->Preprocessor Definitions, just add MY_EXPORTS to the list for dll project, and leave that list without MY_EXPORTS for test project.
And you need define constructor CRootFinder() in RootFinder.cpp.