This question already has an answer here:
I am very new to unit testing and I am a little confused.
I am trying to do unit testing (using the Boost unit testing framework) on a C++ class called VariableImpl
. Here are the details.
class Variable
{
public:
void UpdateStatistics (void) {
// compute mean based on m_val and update m_mean;
OtherClass::SendData (m_mean);
m_val.clear ();
}
virtual void RecordData (double) = 0;
protected:
std::vector<double> m_val;
private:
double m_mean;
};
class VariableImpl : public Variable
{
public:
virtual void RecordData (double d) {
// put data in m_val
}
};
My question is how can I check that the mean is computed correctly? Note that 1) m_mean
is protected and 2) UpdateStatistics
calls a method of another class and then clears the vector.
The only way I can see would be to add a getter (for instance, GetMean
), but I don't like this solution at all, nor I think it is the most elegant.
How should I do?
And what should I do if I were to test a private method instead of a private variable?
TIA,
Jir
In general, I agree with what others have said on here - only the public interface should be unit tested. Nevertheless, I've just had a case where I had to call a protected method first, to prepare for a specific test case. I first tried the
#define protected public
approach mentioned above; this worked with Linux/gcc, but failed with Windows/VisualStudio. The reason was that changingprotected
topublic
also changed the mangled symbol name and thus gave me linker errors: the library provided a protected__declspec(dllexport) void Foo::bar()
method, but with the#define
in place, my test program expected a public__declspec(dllimport) void Foo::bar()
method which gave me an unresolved symbol error.For this reason I switched to a
friend
based solution, doing the following in my class header:And in my actual test case, I did this:
This works with Linux/gcc as well as Windows/VisualStudio.
Unit test VariableImpl such that if its behavior is ensured, so is Variable.
Testing internals isn't the worst thing in the world, but the goal is that they can be anything as long as the interfaces contracts are ensured. If that means creating a bunch of weird mock implementations to test Variable, then that is reasonable.
If that seems like a lot, consider that implementation inheritance doesn't create great separation of concerns. If it is hard to unit test, then that is a pretty obvious code smell for me.