I'm using GoogleTest version 1.7.0 to test my C++ application. I have an enum defined as following
namespace MyNamespace {
enum class MyEnum {
MyEnumValue,
MyEnumValue2
}
}
GoogleTest incorrectly prints it's value, resulting in this error message when the test fails:
Value of: MyClass.MyMethodThatReturnsEnum()
Actual: 4-byte object
Expected: MyEnum::MyEnumValue
Which is: 4-byte object <02-00 00-00>
Removing the class
keyword produces the correct error message with the real value of the enum. Is this a known behaviour/bug of GoogleTest? Is there a way to fix the problem?
MyClass my_class;
EXPECT_EQ(MyEnum::MyEnumValue, my_class.MyMethodThatReturnsEnum());
When you define constants in enum class MyEnum
you define them as objects
of user-defined type MyEnum
from which there is no implicit conversion
to any integral type. That is the goal of enum class
and it's not
for Googletest to assume you want objects of type MyEnum
automatically
converted to an integral type for the purpose of inserting to an output
stream, if you have chosen to make that type an enum class
and not just
an enum
.
So what you observe isn't a Googletest error. It's just Googletest using its
fallback representation of a user-defined object of some type T
for which
std::ostream & operator<<(std::ostream &, T const &);
is undefined.
If you want to see the integral values of objects of type enum class MyEnum
appear in Googletest's diagnostics for a test, you have at least two ways.
One way is to simply apply the test to the underlying integral values of the objects, as in:
main.cpp (1)
#include <gtest/gtest.h>
#include <type_traits>
enum class MyEnum {
Value,
Value2
};
auto as_integral(MyEnum me)
-> std::underlying_type<MyEnum>::type
{
return static_cast<std::underlying_type<MyEnum>::type>(me);
}
TEST(foo,bar)
{
EXPECT_EQ(as_integral(MyEnum::Value),as_integral(MyEnum::Value2));
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Compile, link and run:
$ g++ -std=c++11 -Wall -Wextra -o gtester main.cpp -lgtest -lpthread
$ ./gtester
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from foo
[ RUN ] foo.bar
main.cpp:17: Failure
Expected equality of these values:
as_integral(MyEnum::Value)
Which is: 0
as_integral(MyEnum::Value2)
Which is: 1
[ FAILED ] foo.bar (0 ms)
[----------] 1 test from foo (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (1 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] foo.bar
1 FAILED TEST
Another - better - way is to provide Googletest with a definition of:
std::ostream & operator<<(std::ostream &, MyEnum const &);
that suits you. Then Googletest will use it in its diagnostics, as in:
main.cpp (2)
#include <gtest/gtest.h>
#include <type_traits>
#include <ostream>
enum class MyEnum {
Value,
Value2
};
auto as_integral(MyEnum me)
-> std::underlying_type<MyEnum>::type
{
return static_cast<std::underlying_type<MyEnum>::type>(me);
}
std::ostream & operator<<(std::ostream & out, MyEnum me)
{
return out << as_integral(me);
}
TEST(foo,bar)
{
EXPECT_EQ(MyEnum::Value,MyEnum::Value2);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Compile, link and run:
$ g++ -std=c++11 -Wall -Wextra -o gtester main.cpp -lgtest -lpthread
$ ./gtester
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from foo
[ RUN ] foo.bar
main.cpp:23: Failure
Expected equality of these values:
MyEnum::Value
Which is: 0
MyEnum::Value2
Which is: 1
[ FAILED ] foo.bar (0 ms)
[----------] 1 test from foo (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] foo.bar
1 FAILED TEST
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With