Compare commits

...

7 Commits

Author SHA1 Message Date
jdfa
d5657fc92c
Merge db0e9a6836644ec19fa7ace682f13b3c81eec9e4 into 7140cd416cecd7462a8aae488024abeee55598e4 2026-06-11 19:28:19 +02:00
Mike Kruskal
7140cd416c Flip the recommendation about using EXPECT statements inside custom matchers.
PiperOrigin-RevId: 925686474
Change-Id: I7b5d7e82dc8618d6914844446fa260468b947ece
2026-06-02 18:03:04 -07:00
Abseil Team
a721f1b20c Automated Code Change
PiperOrigin-RevId: 924116072
Change-Id: I3e04ebbff65c897e50c37e1a47a2018f31382104
2026-05-30 20:49:30 -07:00
Aaron Jacobs
8736d2cd5c gmock-spec-builders: support mocking const-qualified function types.
In particular this automatically gives us support for examples like the
following:

    using SomeFn = absl::AnyInvocable<R(Args...) const>;
    MockFunction<SomeFn> some_fn;

PiperOrigin-RevId: 921303527
Change-Id: I19bf59671781e85db65cc20c0d6ea10b056c528a
2026-05-26 01:30:54 -07:00
Abseil Team
09f45f51fb Mark gtest_dt_ptr as const.
PiperOrigin-RevId: 920667027
Change-Id: I3dd71c96e206eb19bf3e62bb08ce7043d83fb526
2026-05-24 16:31:25 -07:00
Andrii Kucherenko
db0e9a6836 Fixed comments 2023-02-03 17:53:13 +02:00
Andrii Kucherenko
31156e74f3 #3683 Added SetMockName function to distinguish between mock objects 2023-01-31 21:03:59 +02:00
8 changed files with 192 additions and 44 deletions

View File

@ -189,6 +189,14 @@ expectations must be matched in a given order, you can use the
[`InSequence` clause](reference/mocking.md#EXPECT_CALL.InSequence) of
`EXPECT_CALL`, or use an [`InSequence` object](reference/mocking.md#InSequence).
## Distinguishing between Unintresting Calls from Different Mocks
By default unintresting mock function calls will be logged as function name and its address.
In case when multiple instances of same mocked class is used it can be useful to set mock name:
```cpp
Mock::SetMockName(&mock_obj, "NamedObject");
```
## Verifying and Resetting a Mock
gMock will verify the expectations on a mock object when it is destructed, or

View File

@ -3386,30 +3386,6 @@ With this definition, the above assertion will give a better message:
Actual: 27 (the remainder is 6)
```
#### Using EXPECT_ Statements in Matchers
You can also use `EXPECT_...` statements inside custom matcher definitions. In
many cases, this allows you to write your matcher more concisely while still
providing an informative error message. For example:
```cpp
MATCHER(IsDivisibleBy7, "") {
const auto remainder = arg % 7;
EXPECT_EQ(remainder, 0);
return true;
}
```
If you write a test that includes the line `EXPECT_THAT(27, IsDivisibleBy7());`,
you will get an error something like the following:
```shell
Expected equality of these values:
remainder
Which is: 6
0
```
#### `MatchAndExplain`
You should let `MatchAndExplain()` print *any additional information* that can
@ -3429,6 +3405,66 @@ the value of `(arg % 7) == 0` can be implicitly converted to a `bool`. In the
`arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be
`unsigned long`; and so on.
#### Anti-pattern: Using EXPECT_ Statements in Matchers
Using `EXPECT_...` statements inside custom matcher definitions is an
**anti-pattern** and should be avoided.
While it might appear to write matchers more concisely and generate informative
messages, this pattern has critical issues:
1. **Negation Breakage (`Not`):** If wrapped in `Not(IsDivisibleBy7())`,
evaluating it still triggers the internal `EXPECT_EQ`, registering a test
failure on the runner even when the overall assertion is expected to
succeed.
2. **Composition / Container Breakage (`AnyOf`, `AllOf`, `Contains`):** When
composed or used inside container matchers, elements that are expected
mismatches will trigger the internal `EXPECT_` and register spurious
failures.
3. **ASSERT_* compilation errors:** `ASSERT_*` macros use `return;` to abort
from a void function. Since matchers return `bool`, using `ASSERT_` inside
them triggers a compilation error.
4. **Purity Violations:** Matchers must be functionally pure (side-effect
free), whereas registering global failures is a major side effect.
5. **Line Number Confusion:** Failure reports point to the matcher's definition
line rather than the calling `EXPECT_THAT`
line.
##### The Anti-Pattern
```cpp
// Anti-pattern: Do not do this!
MATCHER(IsDivisibleBy7, "") {
const auto remainder = arg % 7;
EXPECT_EQ(remainder, 0); // Spurious failures if negated/composed!
return true;
}
```
##### The Correct Solution
To write concise matchers that delegate to other matchers and safely propagate
the mismatch explanation, use **`::testing::ExplainMatchResult`** instead,
passing it the sub-matcher, the value to check, and the `result_listener`:
```cpp
MATCHER(IsDivisibleBy7, "") {
const auto remainder = arg % 7;
return ::testing::ExplainMatchResult(::testing::Eq(0), remainder,
result_listener);
}
```
If you write a test that includes the line:
```cpp
EXPECT_THAT(28, Not(IsDivisibleBy7()));
```
it will correctly report the mismatch, properly point to the `EXPECT_THAT` line
number, and support negation (`Not`) and composition (`AllOf`, `AnyOf`, etc.)
without registering spurious failures.
### Writing New Parameterized Matchers Quickly
Sometimes you'll want to define a matcher that has parameters. For that you can

View File

@ -382,6 +382,15 @@ class GTEST_API_ Mock {
static bool VerifyAndClear(void* mock_obj)
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
// Set name for mock. Will be used in output.
// Useful when multiple instances of same mock is required.
static void SetMockName(void* mock_obj, const std::string& mock_name)
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
// Returns mock name which was set using SetMockName
static std::string GetMockName(const void* mock_obj)
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
// Returns whether the mock was created as a naggy mock (default)
static bool IsNaggy(void* mock_obj)
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex);
@ -1622,6 +1631,8 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
DescribeDefaultActionTo(args, os);
*os << " Function call: " << Name();
UniversalPrint(args, os);
const auto mock_name = Mock::GetMockName(MockObject());
if (!mock_name.empty()) *os << " on " << mock_name;
}
// Returns the expectation that matches the given function arguments
@ -1957,6 +1968,11 @@ struct SignatureOf<R(Args...)> {
using type = R(Args...);
};
template <typename R, typename... Args>
struct SignatureOf<R(Args...) const> {
using type = R(Args...);
};
template <template <typename> class C, typename F>
struct SignatureOf<C<F>,
typename std::enable_if<std::is_function<F>::value>::type>

View File

@ -471,6 +471,7 @@ struct MockObjectState {
int first_used_line;
::std::string first_used_test_suite;
::std::string first_used_test;
::std::string name;
bool leakable; // true if and only if it's OK to leak the object.
FunctionMockers function_mockers; // All registered methods of the object.
};
@ -634,6 +635,22 @@ bool Mock::VerifyAndClear(void* mock_obj)
return VerifyAndClearExpectationsLocked(mock_obj);
}
// Set name for mock. Will be used in output.
// Useful when multiple instances of same mock is required.
void Mock::SetMockName(void* mock_obj, const std::string& mock_name)
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
internal::MutexLock l(&internal::g_gmock_mutex);
g_mock_object_registry.states()[mock_obj].name = mock_name;
}
// Returns mock name which was set using SetMockName
std::string Mock::GetMockName(const void* mock_obj)
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
internal::MutexLock l(&internal::g_gmock_mutex);
if (g_mock_object_registry.states().count(mock_obj) == 0) return "";
return g_mock_object_registry.states()[mock_obj].name;
}
// Verifies and clears all expectations on the given mock object. If
// the expectations aren't satisfied, generates one or more Google
// Test non-fatal failures and returns false.
@ -712,14 +729,13 @@ void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker)
internal::g_gmock_mutex.AssertHeld();
for (MockObjectRegistry::StateMap::iterator it =
g_mock_object_registry.states().begin();
it != g_mock_object_registry.states().end(); ++it) {
it != g_mock_object_registry.states().end();) {
FunctionMockers& mockers = it->second.function_mockers;
if (mockers.erase(mocker) > 0) {
// mocker was in mockers and has been just removed.
if (mockers.empty()) {
g_mock_object_registry.states().erase(it);
}
return;
mockers.erase(mocker);
if (mockers.empty()) {
it = g_mock_object_registry.states().erase(it);
} else {
++it;
}
}
}

View File

@ -942,6 +942,15 @@ static constexpr bool IsMockFunctionTemplateArgumentDeducedTo(
} // namespace
// Like std::add_const, but for function types.
template <typename F>
struct AddConstToFunction;
template <typename R, typename... Args>
struct AddConstToFunction<R(Args...)> {
using type = R(Args...) const;
};
template <typename F>
class MockMethodMockFunctionSignatureTest : public Test {};
@ -953,25 +962,69 @@ TYPED_TEST_SUITE(MockMethodMockFunctionSignatureTest,
TYPED_TEST(MockMethodMockFunctionSignatureTest,
IsMockFunctionTemplateArgumentDeducedForRawSignature) {
using Argument = TypeParam;
MockFunction<Argument> foo;
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
// Non-const
{
using Argument = TypeParam;
MockFunction<Argument> foo;
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
}
// Const
{
using Argument = typename AddConstToFunction<TypeParam>::type;
MockFunction<Argument> foo;
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
}
}
TYPED_TEST(MockMethodMockFunctionSignatureTest,
IsMockFunctionTemplateArgumentDeducedForStdFunction) {
using Argument = std::function<TypeParam>;
MockFunction<Argument> foo;
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
// Non-const
{
using Argument = std::function<TypeParam>;
MockFunction<Argument> foo;
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
}
// As of 2026-05 MSVC doesn't know how to deal with this, providing pages of
// inscrutable errors about std::_Get_function_impl. But this is fine, since
// std::function<R(Args...) const> doesn't apply the const qualifier correctly
// anyway.
#if !defined(_MSC_VER)
// Const
{
using Argument =
std::function<typename AddConstToFunction<TypeParam>::type>;
MockFunction<Argument> foo;
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
}
#endif
}
TYPED_TEST(
MockMethodMockFunctionSignatureTest,
IsMockFunctionCallMethodSignatureTheSameForRawSignatureAndStdFunction) {
using ForRawSignature = decltype(&MockFunction<TypeParam>::Call);
using ForStdFunction =
decltype(&MockFunction<std::function<TypeParam>>::Call);
EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
// Non-const
{
using ForRawSignature = decltype(&MockFunction<TypeParam>::Call);
using ForStdFunction =
decltype(&MockFunction<std::function<TypeParam>>::Call);
EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
}
// Const
{
using ConstTypeParam = typename AddConstToFunction<TypeParam>::type;
using ForRawSignature = decltype(&MockFunction<ConstTypeParam>::Call);
using ForStdFunction =
decltype(&MockFunction<std::function<ConstTypeParam>>::Call);
EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
}
}
template <typename F>

View File

@ -190,6 +190,24 @@ TEST(RawMockTest, InfoForUninterestingCall) {
GMOCK_FLAG_SET(verbose, saved_flag);
}
// Tests that a raw mock using mock name in warnings for uninteresting calls.
TEST(RawMockTest, NamedMockInUninteresingCall) {
MockFoo raw_foo;
const std::string saved_flag = GMOCK_FLAG_GET(verbose);
GMOCK_FLAG_SET(verbose, "info");
const std::string test_name = "NamedMock";
Mock::SetMockName(&raw_foo, test_name);
CaptureStdout();
raw_foo.DoThis();
ASSERT_THAT(GetCapturedStdout(),
HasSubstr("Uninteresting mock function call"));
EXPECT_THAT(GetCapturedStdout(), HasSubstr(test_name));
GMOCK_FLAG_SET(verbose, saved_flag);
}
TEST(RawMockTest, IsNaggy_IsNice_IsStrict) {
MockFoo raw_foo;
EXPECT_TRUE(Mock::IsNaggy(&raw_foo));

View File

@ -129,7 +129,7 @@ class GTEST_API_ Message {
int>::type = 0
#endif // GTEST_HAS_ABSL
>
inline Message& operator<<(const T& val) {
Message& operator<<(const T& val) {
// Some libraries overload << for STL containers. These
// overloads are defined in the global namespace instead of ::std.
//
@ -155,7 +155,7 @@ class GTEST_API_ Message {
template <typename T,
typename std::enable_if<absl::HasAbslStringify<T>::value, // NOLINT
int>::type = 0>
inline Message& operator<<(const T& val) {
Message& operator<<(const T& val) {
// ::operator<< is needed here for a similar reason as with the non-Abseil
// version above
using ::operator<<;

View File

@ -229,7 +229,8 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
if (gtest_dt != nullptr) { \
std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
const std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr( \
gtest_dt); \
switch (gtest_dt->AssumeRole()) { \
case ::testing::internal::DeathTest::OVERSEE_TEST: \
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \