0

I have a problem with testing class with member variable which is not dependent on me. I mean the class contain a variable that is include from other file. And this class throwing error in constructor(no matter why). And then I have a function that uses this variable. So how should I test this class?

// ** classForMe.h can't modify **
class ClassForMe
{
public:
  ClassForMe(){
    // not relevant what should be here but throw error in this case
    throw std::runtime_error("");
  }
  int getData()const {return data;}
...
private:
  int data;
};

other file which contain my class

// C.hpp
#include <classForMe.h>
class C
{
public:
  C():classForMe{}{}
  void save(){
    //some code here, but i need data from ClassForMe
    int i = classForMe.getData();
    ...
  }
private:
  ClassForMe classForMe;
};

If I not clear explained my problem and someone thinking "why you want to testing code which throwing error". This code working well, but not in my platform. For me it throwing error so is posible write test for this class e.g. i emulate that classForMe is construt well and contain some value? And then this value will be used in test of method void save()?

#include <gtest/gtest.h>
#include "C.hpp"
class C_test  : public ::testing::Test
{
 ... ?? 
};
Eoy
  • 9
  • 1
  • 1
    What is the point of faking a test? If you don't care, can't you just not run the test or remove it? – molbdnilo Nov 20 '20 at 12:14
  • I agree with molbnilo. If that test is not meant to pass, then you shouldn't run it. If it's not working on your platform but instead on someone else, then you should conditionally remove the test when compiling on your platform. – Ted Klein Bergman Nov 20 '20 at 12:30
  • The point is testing method save(). But in my case i do not have component in testing environment which is necessary construct classForMe without error. So i want to test it with value not from ClasseForMe. Because I know that this ClassForMe in properly environment will construct fine, but i have to check if method save in my class C work fine when i got this component necessary for ruining ClassForMe without error. – Eoy Nov 20 '20 at 12:34
  • Then the appropriate course of action is to refactor. – molbdnilo Nov 20 '20 at 13:12

1 Answers1

1

In order to test your class C I'd use hi-perf dependency injection to mock ClassForMe (or regular dependency injection if you can create an abstract ClassForMe interface class with all the methods pure virtual). This way you can set expectations for the ClassForMe class in your tests - e.g. different return values of getData when save is called.

struct ClassForMe{
    int getData() const;
};

template<class IMPL = ClassForMe>
class C
{
public:
  C(IMPL& impl):classForMe{impl}{}
  void save(){
    //some code here, but i need data from ClassForMe
    int i = classForMe.getData();

    std::cout << "i is " << i;
    //...
  }
private:
  IMPL& classForMe;
};

struct ClassForMeMock {
    MOCK_METHOD0(getData, int());
};

class C_test  : public ::testing::Test
{
    public:
    ClassForMeMock mock{};
    C<ClassForMeMock> c{mock};
};

TEST_F(C_test, SomeTest) {
    EXPECT_CALL(mock, getData()).WillOnce(testing::Return(42));

    c.save(); // will print "i is 42" to stdout
}
Quarra
  • 2,527
  • 1
  • 19
  • 27
  • I did it, like you described. But in file with test i got error about undefined reference to this mock object. 'undefined reference to C::save()' and 'undefined reference to C::C(ClassForMeMock &)' i had defined constructor and method in my cpp file as: template ` C::C(T& t):classForMe{t}{} template void C::save(){ //... } /... template class C; ` I suppose that I need to add something more here? – Eoy Nov 25 '20 at 13:29
  • I don't think you can define `save` in cpp if you're switching to template-based method - unless you know the types upfront, then you can define the template in the cpp file, see https://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in-a-cpp-file. Otherwise, `class C` must be in header only. – Quarra Nov 25 '20 at 13:38