diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h index 45cc60518..ef199ab86 100644 --- a/googlemock/include/gmock/gmock-spec-builders.h +++ b/googlemock/include/gmock/gmock-spec-builders.h @@ -706,6 +706,12 @@ class GTEST_API_ ExpectationBase { // describes it to the ostream. virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) = 0; + // Do not rely on this for correctness. + // This is only for making human-readable test output easier to understand. + void UntypedDescription(std::string description) { + description_ = std::move(description); + } + protected: friend class ::testing::Expectation; friend class UntypedFunctionMockerBase; @@ -772,6 +778,10 @@ class GTEST_API_ ExpectationBase { retired_ = true; } + // Returns a human-readable description of this expectation. + // Do not rely on this for correctness. It is only for human readability. + const std::string& GetDescription() const { return description_; } + // Returns true if and only if this expectation is satisfied. bool IsSatisfied() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); @@ -831,6 +841,7 @@ class GTEST_API_ ExpectationBase { const char* file_; // The file that contains the expectation. int line_; // The line number of the expectation. const std::string source_text_; // The EXPECT_CALL(...) source text. + std::string description_; // User-readable name for the expectation. // True if and only if the cardinality is specified explicitly. bool cardinality_specified_; Cardinality cardinality_; // The cardinality of the expectation. @@ -909,6 +920,13 @@ class TypedExpectation : public ExpectationBase { return *this; } + // Do not rely on this for correctness. + // This is only for making human-readable test output easier to understand. + TypedExpectation& Description(std::string name) { + ExpectationBase::UntypedDescription(std::move(name)); + return *this; + } + // Implements the .Times() clause. TypedExpectation& Times(const Cardinality& a_cardinality) { ExpectationBase::UntypedTimes(a_cardinality); @@ -1199,10 +1217,15 @@ class TypedExpectation : public ExpectationBase { ::std::ostream* why) GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); + const ::std::string& expectation_description = GetDescription(); if (IsSaturated()) { // We have an excessive call. IncrementCallCount(); - *what << "Mock function called more times than expected - "; + *what << "Mock function "; + if (!expectation_description.empty()) { + *what << "\"" << expectation_description << "\" "; + } + *what << "called more times than expected - "; mocker->DescribeDefaultActionTo(args, what); DescribeCallCountTo(why); @@ -1217,7 +1240,11 @@ class TypedExpectation : public ExpectationBase { } // Must be done after IncrementCount()! - *what << "Mock function call matches " << source_text() << "...\n"; + *what << "Mock function "; + if (!expectation_description.empty()) { + *what << "\"" << expectation_description << "\" "; + } + *what << "call matches " << source_text() << "...\n"; return &(GetCurrentAction(mocker, args)); } diff --git a/googlemock/src/gmock-spec-builders.cc b/googlemock/src/gmock-spec-builders.cc index b333e53da..ea821f855 100644 --- a/googlemock/src/gmock-spec-builders.cc +++ b/googlemock/src/gmock-spec-builders.cc @@ -409,8 +409,15 @@ bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() } else if (!untyped_expectation->IsSatisfied()) { expectations_met = false; ::std::stringstream ss; - ss << "Actual function call count doesn't match " - << untyped_expectation->source_text() << "...\n"; + + const ::std::string& expectation_name = + untyped_expectation->GetDescription(); + ss << "Actual function "; + if (!expectation_name.empty()) { + ss << "\"" << expectation_name << "\" "; + } + ss << "call count doesn't match " << untyped_expectation->source_text() + << "...\n"; // No need to show the source file location of the expectation // in the description, as the Expect() call that follows already // takes care of it. diff --git a/googlemock/test/gmock-spec-builders_test.cc b/googlemock/test/gmock-spec-builders_test.cc index daa109d38..165944ead 100644 --- a/googlemock/test/gmock-spec-builders_test.cc +++ b/googlemock/test/gmock-spec-builders_test.cc @@ -739,11 +739,12 @@ TEST(ExpectCallTest, CatchesTooFewCalls) { EXPECT_NONFATAL_FAILURE( { // NOLINT MockB b; - EXPECT_CALL(b, DoB(5)).Times(AtLeast(2)); + EXPECT_CALL(b, DoB(5)).Description("DoB Method").Times(AtLeast(2)); b.DoB(5); }, - "Actual function call count doesn't match EXPECT_CALL(b, DoB(5))...\n" + "Actual function \"DoB Method\" call count " + "doesn't match EXPECT_CALL(b, DoB(5))...\n" " Expected: to be called at least twice\n" " Actual: called once - unsatisfied and active"); } @@ -1148,10 +1149,11 @@ TEST(ExcessiveCallTest, DoesDefaultAction) { // When there is no ON_CALL(), the default value for the return type // should be returned. MockB b; - EXPECT_CALL(b, DoB(0)).Times(0); + EXPECT_CALL(b, DoB(0)).Description("DoB Method").Times(0); int n = -1; - EXPECT_NONFATAL_FAILURE(n = b.DoB(0), - "Mock function called more times than expected"); + EXPECT_NONFATAL_FAILURE( + n = b.DoB(0), + "Mock function \"DoB Method\" called more times than expected"); EXPECT_EQ(0, n); } @@ -1159,10 +1161,11 @@ TEST(ExcessiveCallTest, DoesDefaultAction) { // the failure message contains the argument values. TEST(ExcessiveCallTest, GeneratesFailureForVoidFunction) { MockA a; - EXPECT_CALL(a, DoA(_)).Times(0); + EXPECT_CALL(a, DoA(_)).Description("DoA Method").Times(0); EXPECT_NONFATAL_FAILURE( a.DoA(9), - "Mock function called more times than expected - returning directly.\n" + "Mock function \"DoA Method\" called more times than expected - " + "returning directly.\n" " Function call: DoA(9)\n" " Expected: to be never called\n" " Actual: called once - over-saturated and active");