0

While trying out HippoMocks (Cygwin, GCC 4.5.3, CppUnit) to mock an interface, one of the methods is causing compilation to fail. Further triage shows that only mocking methods with std::vector as arguments would fail.

e.g.

m_Mocks.ExpectCall(m_EmpSvcMock.get(), IEmployeeServiceProxy::GetEmployees); // compile error!
m_Mocks.ExpectCall(m_EmpSvcMock.get(), IEmployeeServiceProxy::AddEmployee); // compile OK!

where

class IEmployeeServiceProxy
{
public:
    virtual ~IEmployeeServiceProxy() { }
    virtual void AddEmployee(const Employee&) = 0;
    virtual void GetEmployees(std::vector<Employee>&) = 0;
};

struct Employee
{
    boost::uuids::uuid Id;
    std::string Name;
};

Compiler error:

/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/stream_iterator.h: In member function ‘std::ostream_iterator<_Tp, _CharT, _Traits>& std::ostream_iterator<_Tp, _CharT, _Traits>::operator=(const _Tp&) [with _Tp = EmployeeServiceLib::Employee, _CharT = char, _Traits = std::char_traits<char>, std::ostream_iterator<_Tp, _CharT, _Traits> = std::ostream_iterator<EmployeeServiceLib::Employee, char, std::char_traits<char> >]’:
In file included from /usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/iterator:67:0,
                 from /usr/include/boost/uuid/string_generator.hpp:14,
                 from /usr/include/boost/uuid/uuid_generators.hpp:15,
                 from tests/../../RcfTestShared/IEmployeeService.hpp:7,
                 from tests/../IEmployeeServiceProxy.h:11,
                 from tests/ClientTest.h:13,
                 from tests/ClientTest.cpp:8:
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/stl_algobase.h:349:8:   instantiated from ‘static _OI std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = const EmployeeServiceLib::Employee*, _OI = std::ostream_iterator<EmployeeServiceLib::Employee, char, std::char_traits<char> >]’
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/stl_algobase.h:404:70:   instantiated from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false, _II = const EmployeeServiceLib::Employee*, _OI = std::ostream_iterator<EmployeeServiceLib::Employee, char, std::char_traits<char> >]’
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/stl_algobase.h:442:39:   instantiated from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false, _II = __gnu_cxx::__normal_iterator<const EmployeeServiceLib::Employee*, std::vector<EmployeeServiceLib::Employee> >, _OI = std::ostream_iterator<EmployeeServiceLib::Employee, char, std::char_traits<char> >]’
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/stl_algobase.h:474:18:   instantiated from ‘_OI std::copy(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<const EmployeeServiceLib::Employee*, std::vector<EmployeeServiceLib::Employee> >, _OI = std::ostream_iterator<EmployeeServiceLib::Employee, char, std::char_traits<char> >]’
../../RCF/RCF-1.3.1/include/RCF/Tools.hpp:116:9:   instantiated from ‘std::ostream& std::operator<<(std::ostream&, const std::vector<_RealType>&) [with T = EmployeeServiceLib::Employee, std::ostream = std::basic_ostream<char>]’
../../hippomocks/HippoMocks/hippomocks.h:94:5:   instantiated from ‘static void printArg<T>::print(std::ostream&, T, bool) [with T = std::vector<EmployeeServiceLib::Employee>&, std::ostream = std::basic_ostream<char>]’
../../hippomocks/HippoMocks/hippomocks.h:170:5:   instantiated from ‘void ref_tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>::printTo(std::ostream&) const [with A = std::vector<EmployeeServiceLib::Employee>&, B = NullType, C = NullType, D = NullType, E = NullType, F = NullType, G = NullType, H = NullType, I = NullType, J = NullType, K = NullType, L = NullType, M = NullType, N = NullType, O = NullType, P = NullType, std::ostream = std::basic_ostream<char>]’
tests/ClientTest.cpp:47:1:   instantiated from here
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/stream_iterator.h:196:2: error: cannot bind ‘std::ostream_iterator<EmployeeServiceLib::Employee, char, std::char_traits<char> >::ostream_type’ lvalue to ‘std::basic_ostream<char>&&’
/usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/ostream:579:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = EmployeeServiceLib::Employee]’
BЈовић
  • 62,405
  • 41
  • 173
  • 273
Zach Saw
  • 4,308
  • 3
  • 33
  • 49
  • Well you've deleted the error messages now, but in the brief time I saw them I thought the problem was that it was trying to compare Employee objects with operator==. Do you have operator== defined for class Employee? operator== for std::vector will work as long as operator== is defined for T. – jahhaj Aug 02 '12 at 06:11
  • @jahhaj: I've updated HippoMocks to the latest version from their svn and I now have a different error... – Zach Saw Aug 02 '12 at 06:21
  • And the different error is? Also you didn't answer my question, do you have operator== defined for Employee? I would think that is quite important for any unit testing of an Employee class. – jahhaj Aug 02 '12 at 06:24
  • You should define operator==, POD has nothing to do with it. operator== does not get defined automatically even for POD types. – jahhaj Aug 02 '12 at 06:31
  • @jahhaj: Adding the operator doesn't help. Still the same error. – Zach Saw Aug 02 '12 at 06:32
  • Possibly it's complaining that you don't have operator<< defined for Employee, but I'm not certain. I think you've missed the last line of your error messages? In any case I would read the documentation and see what requirements they have for the class being tested. Requiring you to define operator== and operator<< and maybe others is pretty standard for a unit testing framework. – jahhaj Aug 02 '12 at 06:38
  • @jahhaj: You are right. The documentation did mention overloading operator== and operator<< but it mentioned it's only required if "change the way you compare types" and "change the way you print types". And not to mention it's under "Advanced stuff". – Zach Saw Aug 02 '12 at 06:52
  • @jahhaj: write an answer the comments you wrote and I'll make it as correct. – Zach Saw Aug 02 '12 at 06:52
  • It should've converted it to a NotPrintable implicitly and then used its printing logic - in the source around line 350. That explains why it only fails with a vector - the vector itself has an operator<< but the class that it's trying to print doesn't, so it's not HippoMocks failing but rather the vector's operator<< not being well defined (due to you not having an operator<<). I'll add this to the documentation. Thanks! – dascandy Aug 02 '12 at 07:03
  • @dascandy: It looks like the svn trunk version doesn't need operator== in Employee for std::vector too. Could the same be done for operator< – Zach Saw Aug 02 '12 at 07:15

1 Answers1

1

Possibly it's complaining that you don't have operator<< defined for Employee, but I'm not certain. I think you've missed the last line of your error messages? In any case I would read the documentation and see what requirements they have for the class being tested.

Requiring you to define operator== and operator<< and maybe others is pretty standard for a unit testing framework. If you think about it a unit testing framework is going to need to compare objects of the types you are testing and maybe going to try and output those objects when things go wrong.

jahhaj
  • 3,021
  • 1
  • 15
  • 8
  • There's a fix in there to automatically use something else if the class doesn't have an operator<< defined. It'll print "???" instead. There's no default compare anymore as no possible solution would make sense. – dascandy Aug 02 '12 at 06:58
  • @dascandy: I have several questions to follow -- how do I contact you directly rather than asking questions on SO? – Zach Saw Aug 02 '12 at 07:09
  • You can always use my email address dascandy@gmail.com. I just noticed the wiki has gone corrupt - oops... I'll fix that first, it should've had most of the answers but right now it only has a database error. – dascandy Aug 02 '12 at 07:51