Why TEST_F can access the member variable in a class without using any scopes? e.g.,
class ABC : public ::testing::Test
{
protected:
int a;
int b;
void SetUp()
{
a = 1;
b = 1;
}
virtual void TearDown()
{
}
};
TEST_F(ABC, Test123)
{
ASSERT_TRUE(a == b);
}
why it can directly access a and b, instead of using ABC::a or ABC::b? Does the fixture create a variable for class ABC? if so, should it be ASSERT_TRUE(abc.a == abc.b); instead of ASSERT_TRUE(a == b);?
TEST_F is a macro which defines a new class publicly inheriting from the first argument (in this case, 'ABC'). So it has access to all public and protected members of the test fixture class.
You can inspect the source for this macro in the header file to get a better idea of what it's doing.
TEST_F macro, which if you follow the macro path leads you to...
GTEST_TEST_ macro
Related
I am trying to run some google tests, and I have quite a lot of code to repeat in each test fixture, so I want to make the code as brief as possible, and I would like to use the SetUp method of the child class of Testing::test parent class, but the TEST_F fixtures do not recognize the variables from SetUp
This is the simplest example I can come up with:
class FooTest: public testing::Test
{
protected:
virtual void SetUp() // using void SetUp() override does not help
{
int FooVar = 911;
}
virtual void TearDown()
{
}
};
TEST_F(FooTest, SampleTest)
{
// FooTest::SetUp(); // This does not help as well
EXPECT_EQ(911, FooVar);
}
When I try to compile this code it shows an error that FooVar was not declared in this scope. How can I fix it?
Thank you very much for any help.
FooVar is a local variable inside the SetUp method. If you want to use it in the test fixtures, it needs to be a class member:
class FooTest: public testing::Test
{
protected:
int FooVar;
virtual void SetUp() override
{
this.FooVar = 911;
}
};
In this example, if you are only setting integral types, should just make them const member variables.
I am stuck with creating a mock for a concrete class.
I know that is not a great idea to do this but I'm not not allowed to change production code.
My code is similar with:
Class A
{
public:
A(B* b)
{
this->b = b;
}
.........................
void function_from_a_to_test(<arg>)
{
if(!b)
b->function_from_b();
else
//something to do
}
private:
B * b;
};
class B
{
........
public:
void function_from_b();
......
};
class MockB : public B , testing::Mock //i don't know why I can that, B is not virtual
{
MOCK_METHOD(function_from_b, void, (void));
};
A_Test :testing::Test{
SetUp()
{
b = new B();
a = new A(b);
}
TearDown()
{
delete b ;
delete a ;
}
void set_b(B * bb)
{
a->b = bb;
}
.........................
}
In order to test I used Test_f
TEST_F(A_Test, Test_function_from_a_to_test)
{
//arrange
//act
B * b_t = new MockB();
set_b(b_t);
EXPECT_CALL(*(static_cast<MockB> b_t), function_from_b))
.Times(10);
function_from_a_to_test(arg);
}
It's seems that the test is passed but i got memory leak at static cast.
And If I store the result of static cast in another variable (in order to delete it), the expect call having that variable is failing.
I know that is not really a good practice, but I can not change the production code.
Has somebody a idea how to solve it?
Or a better way to test this?
You can't mock a non-virtual function using inheritance. You would have to have to define a mock class that implements the functions needed by the code under test, and then have a way to replace the concrete class with the mock class. Read more about it here.
To be honest, I have no idea what the result of that static_cast is, but it's probably not good.
The only way I can think of to do what you want to do without changing production code is to use a different include path in your test project that would allow completely replacing the concrete class B with the mock class B. This may or may not be possible, depending on how your production code is structured.
If you're lucky enough to have class B defined in a separate header file, then it's easy: Make a mock header file with the same name but different folder, and make sure that folder appears in the include path before the production header file's location.
Production B.h file (in original location and unmodified):
class B
{
public:
void function_from_b() {}
};
Mock B.h file (in test code location):
class B
{
public:
MOCK_METHOD(void, function_from_b, ());
};
Somewhere in production code (unmodified):
#include "B.h" // Will load original or mock depending on include path
class A
{
public:
A(B *b)
{
m_b = b;
}
void function_from_a_to_test(int arg)
{
if (m_b)
m_b->function_from_b();
else
; //something to do
}
private:
B *m_b;
}
Test code:
TEST(A_Test, Test_function_from_a_to_test)
{
B b;
A a(&b);
EXPECT_CALL(b, function_from_b)
.Times(1);
a.function_from_a_to_test(0);
}
I have a test fixture in my tests so I don't have to instantiate objects of my class repeatedly, but I'm not sure how to use mocks with it. To put it simply, this is how the class is defined:
class Class1 {
public:
Class1(std::shared_ptr<Class2> class_two);
void doThisThing() { doThatThing(); }
}
class Class2 {
public:
Class2(Class3* class3_ptr);
int doThatThing();
}
(class 1 is constructed using a shared pointer to class 2. Class 2 is constructed with a pointer to class 3. Class 1 calls on a function "doThisThing" which calls Class 2's function doThatThing.)
I need to create a mock for doThatThing() (and the rest of Class2's functions), but can't figure out how to pass the mock object to Class 1. Here is what I have so far in my testing code:
class TestClass1 : public ::testing::Test {
TestClass1(){
//Construct instance of Class1 and store as member variable
std::shared_ptr<Class3> class_three = std::make_shared<Class3>();
std::shared_ptr<Class2> class_two = std::make_shared<Class2>((Class3*)class_three.get());
class_one = new Class1(class_two);
};
Class1* class_one;
}
MockClass2 : public Class2 {
MOCK_METHOD0(doThatThing, int());
}
TEST_F(TestClass1, doThatThingTest){
MockClass2 mockObj;
**THIS IS WHERE I'M STUCK. How do I get that mockObj into my TestClass1 Fixture? As of now, it is calling the actual function, not the mock***
class_one->doThatThing();
EXPECT_CALL(mockObj, doThatThing());
}
I had to abstract and simplify the actual code, so I hope the above makes sense.
Assuming that your MockClass2 works, you should try something like the following:
Here you should override the functions SetUp that is called right before every call of a test function to prepare your test data. And override TearDown that is called after every call of a test function to clean up test data.
struct TestClass1 : public ::testing::Test
{
void SetUp() override
{
class_two_mock = std::make_shared<MockClass2>();
class_one = std::make_unique<Class1>(class_two_mock);
}
void TearDown() override
{
class_one.reset();
class_two_mock.reset();
}
std::shared_ptr<MockClass2> class_two_mock
std::unique_ptr<Class1> class_one;
};
In the test function you must declare your expectations before something is executed.
TEST_F(TestClass1, doThatThingTest)
{
EXPECT_CALL(*class_two_mock, doThatThing());
class_one->doThatThing();
}
You may need an interface for Class2. The code here is not tested.
I have a class, say ClassA which has some public functions as well as private.
The public functions in turns class private functions.
Now my intention here is to test the private function via public function.
For Public functions, I am trying to invoke the original implementation and for private method I am trying to create a Mock function.
My Class A is like this,
class ClassA {
public:
string getName(string key) {
int value = 2;
int code = getCode(value);
if(code != 2)
cout<<"Error";
else
return "XYZ";
}
private:
int getCode(int value) {
if(value == 2)
return 2;
else
return -1;
}
};
Now I have a Mock for the ClassA like this,
class MockA : public ClassA {
public:
MOCK_METHOD1(getName,string(string key)); //Mock for public method
MOCK_METHOD1(getCode,int(int value))l //Mock for private method
}
This is my GoogleTest test case,
TEST(ClassATest, Test1)
{
MockA a;
Class a1;
EXPECT_CALL(a,getCode()).Times(1).WillOnce(Return(2));
EXPECT_CALL(a,getName()).Times(1).WillOnce(Return(Invoke(&a1,
ClassA::getName());
}
As you can see, for the private method I am using mock and for public method I am using Invoke and invoking the original implementation.
Now, when I compile this code, I get an error,
Actual function call count doesn't match EXPECT_CALL(a,getCode())....
Expected : to be called once
Actual : never called - unsatisfied and active
Now when I try to use orginal Implementation for getCode() also like,
EXPECT_CALL(a,getCode()).Times(1).WillOnce(Return(Invoke(&a1,
ClassA::getCode());
I get an compilation error saying getCode() is inaccesible which I think is expected.
By now, if you are reading this, hope you are understood my problem statement.
I have to test the private method by passing in different arguments, via the public method which I test via gtest.
I wanted to mock the private method as stated by this article in github and call the orininal production code for my public method.
Am I doing something fundamentally wrong? If so, can any of you some better methods for my use case.
I have tried FRIEND_TEST and tbh, I dont want any modifications in my production code. I will try that as a last resort.
You are trying to invoke a private method from ClassA. This is not possible except if there is a friend declaration, but yes, it's not ideal.
The problem stems from the design of your test which should call a public API and not an implementation detail.
Late answer, but I'm currently working on similar issues and saw this question.
In your example I'm not quite sure what the purpose of Invoke() is, but if all you are trying to do is verify calls to getCode() and control its return value, then you would only need to mock that one.
You would have to modify the production code to make the private function virtual, so if that's not an option then of course this wouldn't work for you. It seems like a pretty safe modification though.
class ClassA {
public:
string getName(string key) {
int value = 2;
int code = getCode(value);
if (code != 2)
return "Error";
return "XYZ";
}
private:
virtual int getCode(int value) {
if (value == 2)
return 2;
return -1;
}
};
class MockA : public ClassA {
public:
MOCK_METHOD1(getCode, int(int value));
};
TEST(ClassATest, Test1)
{
MockA mockA;
EXPECT_CALL(mockA, getCode(2)).WillOnce(Return(2));
EXPECT_EQ(mockA.getName("key"), "XYZ");
}
I am trying to access a protected function in class Test but I have no idea how to do it.
Ok I admit one fact that I'm asking this because there's one part of my homework which I am tasked to put a function as protected: and access it instead of putting it to public:
and I am not sure how should I do it.
the code below is how I normally access a function but of course, it doesn't work since it's protected:
Test.h
#ifndef Test_Test_h
#define Test_Test_h
class Test {
protected:
void sampleOutputMethod();
};
#endif
Test.cpp
#include "Test.h"
void Test::sampleOutputMethod() {
std::cout << "this is a test output method" << std::endl;
}
main.cpp
#include Test.h
#include<iostream>
int main() {
Test test;
test.sampleOutputMethod();
}
There are essentially two ways of accessing a protected member:
1) Create a class that inherits from your class Test:
class Test2 : public Test {
public:
void sampleOutputMethod() { ::sampleOutputMethod; }
}
2) Create another class, and modify class Test to make the other class a friend of your Test class:
class Test; // Forward declaration of Test
class Test2 {
public:
void output( Test& foo ) { foo.sampleOutputMethod(); }
}
class Test {
protected:
void sampleOutputMethod();
}
A protected function is just as good as private function if you try to access it from a class that is not part of your hierarchy. You either have to make the class trying to access it a subclass of Test, or you have to declare it as friend class. I bet you need the first option.
You can delegate the function as well. Create a public function that calls the protected one.
This can be accomplished through either deriving Test or creating another class, Test2, and declaring Test a friend of Test2 and having Test2 contain an instance of Test.
Seeing all the instructions of your homework would help.
If you are allowed to modify class Test, you can add a public function which calls "sampleOutputMethod", or you can return function pointer of "sampleOutputMethod" using this trick https://stackoverflow.com/a/6538304/1784418