Error in VS2019 with Google Test when using outside definition - c++

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".

Related

C++ Unit Test in Visual Studio 2019

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

Unit test class unable to find class in another project in the same solution i want to test

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.

"unresolved external..." when trying to build a class with CPP

Today I downloaded the new version of visual studio, and I tried to build a class:
class Fraction
{
public:
Fraction(int, int);
private:
int _a;
int _b;
};
I also built a cpp file for the implementation:
#pragma once
#include "Fraction.h"
#include <string>
Fraction::Fraction(int a, int b)
{
_a = a;
_b = b;
}
The header file (thc class) is in file called "Franctions.h" and found in the header files directory.
The cpp file (thc class) is in file called "Franctions.cpp" and found in the Resource files directory.
When Im trying to run this simple program, I get this issue:
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "public: __thiscall Fraction::Fraction(int,int)" (??0Fraction##QAE#HH#Z) referenced in function _main Homework2 c:\Users\VVV\documents\visual studio 2017\Projects\Homework2\Homework2\questionA.obj 1
Why can it be happening?
EDIT:
main:
#include "Fraction.h"
int main()
{
Fraction f1(1, 2);
return 0;
}
The problem is not within your Fractions.h or Fractions.cpp, but rather with questionA.cpp note that the referencing file that cannot find the symbol in the error is:
c:\Users\VVV\documents\visual studio 2017\Projects\Homework2\Homework2\questionA.obj
Is #include "Fractions.h" in that file?
this error means that the compiler can't find this function.
write the specific place in the include path and see if it solve your problem.
if so, it means your header file is looking at different directory than the one you think.

Creating class object defined in another project

I have a Visual C++ solution with 2 projects: rectangle and project3.
In rectangle project I have rect.cpp and rect.h.
rect.h
#ifndef rect_h
#define rect_h
class Rect
{
public:
Rect();
int m_h;
int m_w;
};
#endif //rect_h
rect.cpp
#include "rect.h"
Rect::Rect()
{
m_h = 1;
m_w = 5;
}
whenever I try to create rect object from the rectangle project it succeeds.
But when I try to do the same from the project3 it produces a linker error.
LNK2019: unresolved external symbol "public: __thiscall
Rect::Rect(void)" (??0Rect##QAE#XZ) referenced in function _main
1>C:\Users\mbaro\documents\visual studio
2017\Projects\Project2\Debug\Project3.exe : fatal error LNK1120: 1
unresolved externals
main.cpp (in project 3)
#include "rect.h"
using namespace std;
int main()
{
Rect* a = new Rect();
return 0;
}
I kind of feel that class definition is picked up successfully, but the linker can not link the constructor code from rect.cpp.
What is the problem and how to solve it?
Thanks.
The error is normal: you told the compiler where it could find the .h files, but you did not tell the linker where it could find the .obj files.
It may depend on the exact VS version, but in Project/Properties, you should find Linker/Input and there Additional dependencies. If you only need one or two object files (xxx.obj) from the other project, add them here. That way, you avoid code duplication, which will be a nightmare for future maintenance...
If you have many common files, you should considere to put them in an auxilliary project that would build a (static)library in the same solution, and then link the library in both project (and of course give access to header files of the library project for the other projects using the library).
I have already started writing a long, long answer. Then i realized, what You may be missing is that despite Your class is named "Person" the header file You should have added is named "rect.h".
Also Your constructor cannot have a declaration of values in the header file (EDIT:not true, I was mistaken). In the header file, try using:
Person(int h, int w);
You declare what will be needed, not what You already have. If You want those to be specifically what You wrote the constructor should be:
Person();
in .h
and
Person::Person()
{
m_h = 1;
m_w = 5;
}
in .cpp.
If You need more detailed description of using include, I have already written a big part of it, so don't hesitate to ask.

c++ compiling issue -- Compiles fine with cl.exe but will not compile from Visual Studio 2015

******* EDIT *******
One reader suggested that my question was a duplicate of the question found here. The leading response to this question gives two solutions:
1) #include the implementation file at the end of the header (which is what I did in my solution) or
2) explicitly instantiate all of the template instances I'll need at the end of the implementation file
Since I had already attempted this solution, this is not a duplicate question.
The problem, as addressed by Ben Voigt below (thank you), has to do with Visual Studio. Changing the "Item Type" from "C/C++ compiler" to "C/C++ header" for the MyClass.cpp file resolved the issue.
**** END EDIT ****
I'm a beginner to c++ and I'm running into an issue trying to compile the following program in Visual Studio 2015. The program compiled fine using the clang compiler on my Mac. The program also compiled fine using cl.exe from the Developer Command Prompt for VS2015. I guess this means something is configured wrong in my Visual Studio project, but I haven't found a solution.
Here's the code:
/** #file MyInterface.h */
#ifndef MY_INTERFACE_
#define MY_INTERFACE_
template<class ItemType>
class MyInterface
{
public:
virtual void sayHello() const = 0;
};
#endif
/** #file MyClass.h */
#ifndef MY_CLASS_
#define MY_CLASS_
#include "MyInterface.h"
template<class ItemType>
class MyClass : public MyInterface<ItemType>
{
private:
ItemType myItem;
public:
MyClass();
void setItem(const ItemType& newItem);
void sayHello() const;
};
#include "MyClass.cpp"
#endif
/** Implementation file for MyClass.
#file MyClass.cpp */
#include "MyClass.h"
#include <iostream>
template<class ItemType>
MyClass<ItemType>::MyClass()
{
}
template<class ItemType>
void MyClass<ItemType>::setItem(const ItemType& newItem)
{
myItem = newItem;
}
template<class ItemType>
void MyClass<ItemType>::sayHello() const
{
std::cout << "Hello! My Item is: " << myItem << std::endl;
}
/** #file test.cpp */
#include "MyClass.h"
#include <string>
int main()
{
MyClass<std::string> classOne;
classOne.setItem("foo");
classOne.sayHello();
MyClass<int> classTwo;
classTwo.setItem(7);
classTwo.sayHello();
}
When I combine these files in one directory and run the command:
cl test.cpp
from the Developer Command Prompt for VS2015, it correctly compiles. I get a test.exe executable file which returns:
test.exe
Hello! My item is: foo
Hello! My item is: 7
So far, so good.
The problem begins when I try to complete this project inside of Visual Studio 2015. I started an "Empty Project" for Visual c++ and added these exact same files. However, when I build the project I get the error messages:
Error C2995 'MyClass<ItemType>::MyClass(void)': function template has already been defined
Error C2995 'void MyClass<ItemType>::setItem(const ItemType &)': function template has already been defined
Error C2995 'void MyClass<ItemType>::sayHello(void) const': function template has already been defined
The error message leads me to believe that I have a circular dependency. The culprit appears to be the #include "MyClass.cpp" in the MyClass.h file, but this is necessary for the template to compile. Without this inclusion, the compiler cannot see the instantiation of the template and does not know the actual data type corresponding to the generic type ItemType (or so my textbook says).
In an effort to satisfy the Visual Studio build process, I removed the #include "MyClass.cpp from the MyClass.h file, but then I get THESE errors:
Error LNK2019 unresolved external symbol "public: __thiscall MyClass<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::MyClass<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(void)" (??0?$MyClass#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std####QAE#XZ) referenced in function _main
Error LNK2019 unresolved external symbol "public: __thiscall MyClass<int>::MyClass<int>(void)" (??0?$MyClass#H##QAE#XZ) referenced in function _main
Error LNK2019 unresolved external symbol "public: void __thiscall MyClass<int>::setItem(int const &)" (?setItem#?$MyClass#H##QAEXABH#Z) referenced in function _main
There were six such errors (only three are shown), all being unresolved external symbols.
At this point I don't know what else to try. If I include the implementation file in the header, the compiler yells at me for having circular dependencies, and if I DON'T include the implementation file in the header, I have unresolved external symbols.
Any help on this problem would be much appreciated :)
Because you #include MyClass.cpp, it isn't a compilation unit itself, it's a header file. Make sure Visual Studio is told not to try to build it separately, by default it assumes .h files are headers and .cpp are each individually compiled units.
Access the item properties and change "Item Type" from "C/C++ compiler" to "C/C++ header".
This effectively changes the build command to the working version
cl test.cpp
from the default (effective) command generated by adding all the files
cl test.cpp MyClass.cpp
which would cause exactly the same errors if you typed that at the command line.
There are other ways to accomplish removing it from the build command, like "Exclude file from project", found on the right-click menu in Solution Explorer, but that makes it less convenient to edit/navigate to. Marking it correctly as a header file will give you the best experience for Intellisense auto-completion, Goto Definition, and source view during debugging.