Writing Unit-Test for a Class - c++

I have a class with constructor having 6 arguments. I want to write a Test fixture for this class. I tried calling these arguments in the test constructor, but failed to create test fixture
class TestHandler
{
public:
using Buffer = common::dt::ByteBuffer;
using HardwareInterface =
common::interfaces::SyncBufferProducerConsumer<Buffer>;
explicit TestHandler(slave::cache::FullKeyValueCache&
cache, const CommandHandler& commandHandler,
const RTDCache& rtdCache, HardwareInterface&
hardwareInterface, bool& statusChanged, bool& alarmsChanged)
: m_keyValueCache(cache)
, m_commandHandler(commandHandler)
, m_rtdCache(rtdCache)
, m_hardwareInterface(hardwareInterface)
, m_statusChanged(statusChanged)
, m_alarmsChanged(alarmsChanged)
{
}
template <typename T>
void respond()
{
m_checksumHelper.checksumEnabled() =
m_commandHandler.checksumEnabled();
auto responseMessage =
SalviaSerial::traitsTemplate::Response();
fillResponse<T>(responseMessage);
common::dt::GuardedWriteBuffer<uint8_t>
writeBuffer(m_hardwareInterface);
common::extensionCards::library::serialise
(responseMessage, writeBuffer.get_range());
m_checksumHelper.calculateAndSetChecksum
(writeBuffer.get_range());
}
private:
template <typename T>
void fillResponse(SalviaSerial::traitsTemplate::Response&
response);
slave::cache::FullKeyValueCache& m_keyValueCache;
const CommandHandler& m_commandHandler;
const RTDCache& m_rtdCache;
HardwareInterface& m_hardwareInterface;
DOBusImplementation::ChecksumHelper m_checksumHelper;
bool& m_statusChanged;
bool& m_alarmsChanged;
};
I need to write a Test fixture for TestHandler class, later use this t4xt fixture to test different responses available. I need suggestions on calling this class in TestHandlerTest.cpp and a method to start unit test.

If you want to create a test fixture in Google Test, you’ll need to (a) inherit from the testing::Test class and (b) ensure your fixture class is default-constructible (can be constructed without any arguments).

Related

gmock: force mocking out of a class method without defining and referencing a mock class?

the normal pattern of gmock testing is
class MyMockClass : public MyRealClass {
/// swap out behavior of an existng method
MOCK_method(some_method .....);
}
TEST() {
MyMockClass mock;
EXPECT_CALLED(mock.some_method);
/// ******* here I have to explicitly pass in the mock obj into the system
MyConsumerClass myconsumer(mock);
myconsumer.do_something_to_trigger_mock__some_method();
}
in the above "****" line I have to explicitly pass in a mock obj into the system, i.e. compose my consumer obj with a mock obj. But now I face an existing consumer class impl, its constructor does not allow passing in the dependency objects; in fact I can probably argue that it's impossible to list all the dependency objects in the ctor of a consumer class; more importantly, my real case is that the consumer class to be tested sits several levels above the mock obj:
class MyConsumerClass {
private:
MyHelperClass helper
public:
void trigger() {
helper.trigger_again();
}
}
class MyHelperClass {
BottomClass bottom;
public:
void trigger_again() {
bottom.do_something();
}
}
class BottomClass {
public :
void do_something();
}
in this case, in our unit test, we can only instantiate the top level MyConsumerClass, and I was hoping to verify that when I call myconsumer.trigger(), I could verify that the BottomClass.do_something() is called, possibly also verifying that it's called with a specific argument. But the above class hierarchy is written so that I can not pass in a mock BottomClass obj from the top level.
in jmock or jmockit, I remember it's possible to globally wipe out the behavior of BottomClass.do_something(), without referring to a specific mock obj, i.e. "static mocking", as they are called in jmockit. is it possible to do something like that in gmock (c++)? thanks
Converting the comment to an answer:
I can think of two things:
Why don't you test your classes separately? For example, write a separate test for MyHelperClass.
If dependency injection doesn't work for you, GMock allows you to do static mocking by templatizing your classes: Convert your classes to templates, then instantiate the template with real classes for production and with mock classes for testing. See here for an example.
In your case, your code could be rewritten to something like this:
//-----------------------------------------------------------------------------
// Real classes used in production
//-----------------------------------------------------------------------------
class BottomClass {
public:
void do_something();
};
//-----------------------------------------------------------------------------
// Templatized classes used in test or production
//-----------------------------------------------------------------------------
template <class BType>
class MyHelperClass {
public:
BType bottom;
public:
void trigger_again() { bottom.do_something(); }
};
template <class BType, template <typename> class HType>
class MyConsumerClass {
public:
HType<BType> helper;
public:
void trigger() { helper.trigger_again(); }
};
//-----------------------------------------------------------------------------
// Mocked classes used in test
//-----------------------------------------------------------------------------
class MockedBottomClass {
public:
MOCK_METHOD(void, do_something, (), ());
};
TEST(BottomClassTest, Test1) {
MyConsumerClass<MockedBottomClass, MyHelperClass> mock;
EXPECT_CALL(mock.helper.bottom, do_something());
mock.trigger();
}
I had to convert some of your private members to public members for the test to work.
Live example here: https://godbolt.org/z/qc3chdxKz

Why does GMOCK object not return values set by EXPECT_CALL in dependency injection

I have the following object that I want to mock:
class Esc {
public:
Esc() = default;
virtual ~Esc() {}
virtual int GetMaxPulseDurationInMicroSeconds() const noexcept{
return 100;
}
};
I wrote this mock:
class MockEsc : public Esc {
public:
MockEsc(){}
MockEsc(const MockEsc&){}
MOCK_METHOD(int, GetMaxPulseDurationInMicroSeconds, (), (const, noexcept, override));
};
And this is the unit under test which calls the aforementioned Esc.GetMaxPulseDurationInMicroSeconds() method
class LeTodar2204{
public:
LeTodar2204() = delete;
explicit LeTodar2204(std::unique_ptr<Esc> esc) : esc_(std::move(esc)){}
int CallingMethod(){
int a = esc_->GetMaxPulseDurationInMicroSeconds();
return a;
}
private:
std::unique_ptr<Esc> esc_;
In the SetUp of my testfixture I want to set my mock to return a 1 and inject it into the unit under test.
class Letodar2204Tests : public ::testing::Test {
protected:
Letodar2204Tests() {}
virtual void SetUp() {
EXPECT_CALL(esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
unit_under_test_ = std::make_unique<propulsion::LeTodar2204>(std::make_unique<MockEsc>(esc_));
}
MockEsc esc_;
std::unique_ptr<propulsion::LeTodar2204> unit_under_test_;
};
Now in the test I call the method that should call the mocked method, but GetMaxPulseDurationInMicroSeconds of my mocked object only returns 0 (aka the default value) and warns me about the uninteresting function call.
This is the test
TEST_F(Letodar2204Tests, get_pulse_duration) {
EXPECT_CALL(esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
auto duration = unit_under_test_->CallingMethod();
ASSERT_EQ(duration, 1);
}
What am I missing?
Because you are effectively assigning expectation to an object which you'll be copying anyway. esc_ default ctor is going to be called once Letodar2204Tests is instantiated. Now, in SetUp you assign an expectation on class' field esc_, and then, basing on esc_ create a brand new object (on the heap, using make_unique) using its copy-ctor. Expectations are not going to be magically copied as well. I believe you should store an unique_ptr<MockEsc> esc_ as a class' field, instantiate it on heap within SetUp and inject to LeTodar:
class Letodar2204Tests : public ::testing::Test {
protected:
Letodar2204Tests() {}
virtual void SetUp() {
esc_ = std::make_unique<MockEsc>();
EXPECT_CALL(*esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
unit_under_test_ = std::make_unique<propulsion::LeTodar2204>(esc_);
}
std::unique_ptr<MockEsc> esc_;
std::unique_ptr<propulsion::LeTodar2204> unit_under_test_;
};
Here, you are implicitly calling copy-ctor: std::make_unique<MockEsc>(esc_)
You could do a simple test: mark copy ctor in MockEsc 'deleted' and you'll see that your project no longer compiles (at least it shouldn't be :D)

Specify constructor arguments for a Google test Fixture

With Google test I want to specify a Test fixture for use in different test cases.
The fixture shall allocate and deallocate objects of the class TheClass and its data management class TheClassData, where the data management class requires the name of a datafile.
For the different tests, the file name should vary.
I defined the following Fixture:
class TheClassTest : public ::testing::Test {
protected:
TheClassTest(std::string filename) : datafile(filename) {}
virtual ~TheClassTest() {}
virtual void SetUp() {
data = new TheClassData(datafile);
tc = new TheClass(data);
}
virtual void TearDown() {
delete tc;
delete data;
}
std::string datafile;
TheClassData* data;
TheClass* tc;
};
Now, different tests should use the fixture with different file names.
Imagine this as setting up a test environment.
The question: How can I specify the filename from a test, i.e. how to call a non-default constructor of a fixture?
I found things like ::testing::TestWithParam<T> and TEST_P, which doesn't help, as I don't want to run one test with different values, but different tests with one fixture.
As suggested by another user, you cannot achieve what you want
by instantiating a fixture using a non-default constructor. However,
there are other ways. Simply overload the SetUp function and
call that version explicitly in the tests:
class TheClassTest : public ::testing::Test {
protected:
TheClassTest() {}
virtual ~TheClassTest() {}
void SetUp(const std::string &filename) {
data = new TheClassData(filename);
tc = new TheClass(data);
}
virtual void TearDown() {
delete tc;
delete data;
}
TheClassData* data;
TheClass* tc;
};
Now in the test simply use this overload to set up filename:
TEST_F(TheClassTest, MyTestCaseName)
{
SetUp("my_filename_for_this_test_case");
...
}
The parameterless TearDown will automatically clean up when
the test is complete.
Use the current class as a base class for your fixtures:
class TheClassTestBase : public ::testing::Test {
protected:
TheClassTestBase(std::string filename) : datafile(filename) {}
...
};
For every specific filename - use derived fixture:
class TheClassTestForFooTxt : public TheClassTestBase {
protected:
TheClassTestForFooTxt() : TheClassTestBase ("foo.txt") {}
};
However this is extra step needed for every set of parameters - so you can try to use templates or macros to get it done with less effort. Like:
template <typename ClassTestTag>
struct ClassTestParams
{
static std::string filename;
};
template<typename ClassTestTag>
class TheClassTest : public TheClassTestBase {
protected:
TheClassTest() : TheClassTestBase (ClassTestParams<ClassTestTag>::filename) {}
};
Then - for every set of parameters - do that:
class FooTxtTag {};
template <> std::string ClassTestParams<FooTxtTag>::value = "foo.txt";
using TheClassTestForFooTxt = TheClassTest<FooTxtTag>;
TEST_F(TheClassTestForFooTxt, xxxx) {}
However - in your specific case - I would also try GoogleTest:type-parameterized-tests.
Another great way to deal with this is to just extend your fixture and in the extended class supply a new default constructor which calls through to the old one with the arguments you require. For example:
struct MySpecializedTestFixture : public GenericTestFixture
{
MySpecializedTestFixture() : GenericTestFixture("a thing", "another thing") {}
};
TEST_F(MySpecializedTestFixture, FancyTest)
{
// Use the thing environment and make some assertions.
}
If you overload the SetUp method as suggested here, and you want to ensure that you remember to use the overloaded SetUp, you can use an assertion in the TearDown method.
class my_fixture : public ::testing::Test
{
protected:
bool SETUP_HIT_FLAG = false;
void SetUp(double parameter)
{
...
SETUP_HIT_FLAG = true;
}
void TearDown() override
{
assert(SETUP_HIT_FLAG && "You forgot to call SetUp with your parameter!");
}
};
Another way using templates:
template<int N>
class Fixture : public ::testing::Test { ... }
using FixtureForTest = Fixture<1000>;
TEST_F(FixtureForTest, test) { ... }
For this specific case, I feel it is much easier to get rid of the test fixture altogether. The SetUp function can instead be replaced with a helper function that instantiates the class with the required file name. This permits the use of TEST instead of TEST_P or TEST_F. Now each test case is a standalone test which creates its own test class instances with the helper function or directly in the body of the test case.
For example:
using namespace testing;
TEST(FooClassTest, testCase1)
{
FooClass fooInstance("File_name_for_testCase1.txt");
/* The test case body*/
delete fooInstance;
}

How to make expectations on a mock object created inside the tested object?

I want to unit test a class that looks like this:
template <typename T>
class MyClass {
...
void someMethod() {
T object;
object.doSomething();
}
...
};
I want to unit test this class, so I create a mock class for T:
struct MockT {
...
MOCK_METHOD(doSomething, 0, void());
...
};
Then I want to use it in a test case:
BOOST_AUTO_TEST_CASE(testSomeMethod) {
MyClass<MockT> myClassUnderTest;
MOCK_EXPECT(???)....;
myClassUnderTest.someMethod();
}
How do I make an expectation for this object? My first idea was to store all created MockT instances in a static container from the constructor, then delete them from the container from the destructor. This would work if the object were created in a different method than where it is used, like this:
myClassUnderTest.createTheObject();
MOCK_EXPECT(MockT::findMyObject().doSomething);
myClassUnderTest.useTheObject();
But for this I would need to modify the interface of my class, and I really don't want to do that. Is there anything else I can do?
You can use Typemock Isolator++ if you don't want to modify your interface or introduce extra indirection.
template <typename T>
class MyClass
{
public:
void someMethod()
{
T object;
object.doSomething();
}
};
class RealType //RealType is the actual production type, no injection needed
{
public:
void doSomething(){}
};
Since T is created inside someMethod (inside under test method), we need to fake the T's ctor.
FAKE_ALL does just that. The behavior set on fakeRealType will apply to all RealType instances created in runtime. The default FAKE_ALL behavior is a recursive fake, meaning that all the fakes's methods are faked and will return fake objects. You can also manually set any behavior you want on any method.
TEST_CLASS(MyTests)
{
public:
TEST_METHOD(Faking_Dependency_And_Asserting_It_Was_Called)
{
RealType* fakeRealType= FAKE_ALL<RealType>();
MyClass<RealType> myClassUnderTest;
myClassUnderTest.someMethod();
ASSERT_WAS_CALLED(fakeRealType->doSomething());
}
};
Typemock fakes are not strict, so you need to write an appropriate assert to make sure that your method was indeed called. You can do it using ASSERT_WAS_CALLED which is also provided by Typemock.
P.S I used MSTest.
You could redirect the doSomething member function to a static one e.g.
struct MockT
{
void doSomething() {
soSomethingS();
}
MOCK_STATIC_FUNCTION( doSomethingS, 0, void(), doSomething )
};
Then your test would be
BOOST_AUTO_TEST_CASE(testSomeMethod) {
MyClass<MockT> myClassUnderTest;
MOCK_EXPECT(MockT::doSomething).once();
myClassUnderTest.someMethod();
}
If needed you can test the construction and destruction of the object instance, but it likely doesn't bring much more to your test.
I found that the best is to use a shared pointer for the member. It is unfortunate that I have to use an extra indirection just because of the unit test, but at least it works well.
template <typename T, typename TFactory>
class MyClass {
...
void someMethod() {
std::shared_ptr<T> object = factory();
object->doSomething();
}
...
TFactory factory;
};
Then in the test it looks something like this:
BOOST_AUTO_TEST_CASE(testSomeMethod) {
std::shared_ptr<T> mockT;
MockTFactory factory(mockT);
MyClass<MockT, MockTFactory> myClassUnderTest(factory);
MOCK_EXPECT(mockT->doSomething).once();
myClassUnderTest.someMethod();
}

gmock mock class does not inherit any classes

I have see some sample code about gmock,
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <stdio.h>
#include <string>
class MockFoo {
public:
MockFoo() {}
MOCK_METHOD3(Bar, char(const std::string& s, int i, double x));
MOCK_METHOD2(Bar2, bool(int x, int y));
MOCK_METHOD2(Bar3, void(int x, int y));
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
};
class GMockOutputTest : public testing::Test {
protected:
MockFoo foo_;
};
TEST_F(GMockOutputTest, ExpectedCall) {
testing::GMOCK_FLAG(verbose) = "info";
EXPECT_CALL(foo_, Bar2(0, _));
foo_.Bar2(0, 0); // Expected call
testing::GMOCK_FLAG(verbose) = "warning";
}
The mock class MockFoo is mocking three functions as is in the class body, but the class MockFoo does not inherit any class.
If I understand it correctly, the mock class can mock virtual and non-virtual functions.
1) Mocking virtual functions: mock class should inherit a base class being mocked, and all the functions in that class should be virtual, but in this example, there is no base class.
2) Mocking non-virtual functions: mock class does not need inherit any class, but it needs to add tamplate to the code in order to use hi-perf dependency injection.
Does the code above belong to any of the case? And what is it trying to mock? And how to understand it?
The key thing to remember here is that a mock class can override either virtual or non-virtual methods in a superclass, but it doesn't have to. Sometimes it's useful to define a totally standalone mock which doesn't conform to any particular interface or override any other functionality. Consider the case where you are testing a templatized class:
template <typename T>
class Foo {
public:
Foo(T* member) : _member(member) {}
void f() { _member->bar(); }
private:
T* _member;
};
You want to verify that class Foo invokes bar() on the template parameter class, but the template class doesn't need to conform to any formal interface; it just needs to expose a bar() method. In this case you might use a standalone mock:
class MockSomething {
public:
MOCK_METHOD0(bar, void());
};
Just like your example, this mock class has no relationship to another class or interface. It's a standalone mock, and it can be used just as you would any other:
TEST(StackOverflow, StandaloneMock) {
MockSomething mock;
EXPECT_CALL(mock, bar());
Foo<MockSomething> foo(&mock);
foo.f();
}
That code is to test the method Bar2() of template class NaggyMock. To be more precise, it is testing that when you call method Bar2() with parameters 0 and 0, that Bar2() method from the mock is going to be called.
You can look at that as a static dependency injection, since you inject dependency through a template parameter. I would say it is the case 2.
Assuming your template class NaggyMock looks like this :
template< typename Foo >
class NaggyMock
{
public:
bool Bar2(int x, int y)
{
if ( ( 0 == x ) && ( 0 == y ) )
{
return foo.Bar2( 0, 11 );
}
return false;
}
private:
Foo foo;
};
then in the unit test you are testing the case when both parameters are 0. If your real class is using some resource (reading from a network, or from a database, or a file, ...), then to avoid it, and make your unit test very fast, you are going to mock that object. And that is what you are doing. Instead of the class handing the real resource, you are injecting a mock object.
For more information, read :
What is Mocking?
Why prefer template method over dependency injection?