I'm writing unit tests and trying to have all my code covered.
I have in my code something like this:
template<typename ValueType>
std::string ConvertToStringUsingBoost(ValueType const& v)
{
try
{
return boost::lexical_cast<std::string, ValueType>(v);
}
catch(boost::bad_lexical_cast const& e)
{
LOG_ERR("Fail to cast %s to string", e.source_type().name);
return std::string();
}
}
I was reading these docs and couldn't find any information about when boost::lexical_cast
to std::string
can throw an exception.
Can you please help me with that?
If it's impossible I'll simply delete this try-catch. If it's possible, I'd prefer to cover this in unit testing.
I can't think of any reason for lexical cast to string to throw bad_lexical_cast
, except with user-defined types. If the ValueType
stream insertion operator can set an error flag on the stream then that's going to result in a bad_lexical_cast
. Otherwise, not.
Personally I'd keep the catch
in, even if you're just converting built-ins like int
s; it doesn't hurt, and may catch bugs if you change the lexical_cast
in some manner, or if there's some edge case that neither you nor I has considered; if you're not handling the resulting exception, you'll get an abort at runtime!
If you're concerned about the overhead of an exception, you can use try_lexical_cast
instead and check that it returns true
rather than catching. However, if the ValueType
stream insertion operator can throw then you'd still need to be able to catch that exception anyway.
It can fail for example if a user-defined conversion throws:
enum class MyType {};
std::ostream& operator<<( std::ostream&, MyType const& )
{
throw "error";
}
int main()
{
try
{
boost::lexical_cast< std::string >( MyType{} );
}
catch(...)
{
std::cout << "lexical_cast exception";
}
}
As you have no control about the type of exceptions thrown by user-defined conversions, catching boost::bad_lexical_cast
won't even be enough. Your unit test has to catch all exceptions.
The only safe and futureproof (eg. no nasty surprises after an update of boost ) is to impair your code with something (ugly) like this:
template<typename ValueType>
std::string ConvertToStringUsingBoost(ValueType const& v)
{
try
{
#ifdef UNITTEST
if (unittest == case_fail) {
throw boost::bad_lexical_cast();
}
#endif
return boost::lexical_cast<std::string, ValueType>(v);
}
catch(boost::bad_lexical_cast const& e)
{
LOG_ERR("Fail to cast %s to string", e.source_type().name);
return std::string();
}
}
Now you should be able to get to that ~100% code coverage !
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.