mirror of
https://github.com/google/googletest.git
synced 2024-12-27 10:11:03 +08:00
Add support for std::function in MockFunction (#2277)
This commit is contained in:
parent
e41f31f2af
commit
53740ebc21
@ -1786,10 +1786,80 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
|
|||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// A MockFunction<F> class has one mock method whose type is F. It is
|
namespace internal {
|
||||||
// useful when you just want your test code to emit some messages and
|
|
||||||
// have Google Mock verify the right messages are sent (and perhaps at
|
template <typename F>
|
||||||
// the right times). For example, if you are exercising code:
|
class MockFunction;
|
||||||
|
|
||||||
|
template <typename R, typename... Args>
|
||||||
|
class MockFunction<R(Args...)> {
|
||||||
|
public:
|
||||||
|
MockFunction(const MockFunction&) = delete;
|
||||||
|
MockFunction& operator=(const MockFunction&) = delete;
|
||||||
|
|
||||||
|
std::function<R(Args...)> AsStdFunction() {
|
||||||
|
return [this](Args... args) -> R {
|
||||||
|
return this->Call(std::forward<Args>(args)...);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation detail: the expansion of the MOCK_METHOD macro.
|
||||||
|
R Call(Args... args) {
|
||||||
|
mock_.SetOwnerAndName(this, "Call");
|
||||||
|
return mock_.Invoke(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
MockSpec<R(Args...)> gmock_Call(Matcher<Args>... m) {
|
||||||
|
mock_.RegisterOwner(this);
|
||||||
|
return mock_.With(std::move(m)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
MockSpec<R(Args...)> gmock_Call(const WithoutMatchers&,
|
||||||
|
R (*)(Args...)) {
|
||||||
|
return this->gmock_Call(::testing::A<Args>()...);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MockFunction() = default;
|
||||||
|
~MockFunction() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionMocker<R(Args...)> mock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
The SignatureOf<F> struct is a meta-function returning function signature
|
||||||
|
corresponding to the provided F argument.
|
||||||
|
|
||||||
|
It makes use of MockFunction easier by allowing it to accept more F arguments
|
||||||
|
than just function signatures.
|
||||||
|
|
||||||
|
Specializations provided here cover only a signature type itself and
|
||||||
|
std::function. However, if need be it can be easily extended to cover also other
|
||||||
|
types (like for example boost::function).
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
struct SignatureOf;
|
||||||
|
|
||||||
|
template <typename R, typename... Args>
|
||||||
|
struct SignatureOf<R(Args...)> {
|
||||||
|
using type = R(Args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
struct SignatureOf<std::function<F>> : SignatureOf<F> {};
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
using SignatureOfT = typename SignatureOf<F>::type;
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// A MockFunction<F> type has one mock method whose type is
|
||||||
|
// internal::SignatureOfT<F>. It is useful when you just want your
|
||||||
|
// test code to emit some messages and have Google Mock verify the
|
||||||
|
// right messages are sent (and perhaps at the right times). For
|
||||||
|
// example, if you are exercising code:
|
||||||
//
|
//
|
||||||
// Foo(1);
|
// Foo(1);
|
||||||
// Foo(2);
|
// Foo(2);
|
||||||
@ -1823,49 +1893,33 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
|
|||||||
// Bar("a") is called by which call to Foo().
|
// Bar("a") is called by which call to Foo().
|
||||||
//
|
//
|
||||||
// MockFunction<F> can also be used to exercise code that accepts
|
// MockFunction<F> can also be used to exercise code that accepts
|
||||||
// std::function<F> callbacks. To do so, use AsStdFunction() method
|
// std::function<internal::SignatureOfT<F>> callbacks. To do so, use
|
||||||
// to create std::function proxy forwarding to original object's Call.
|
// AsStdFunction() method to create std::function proxy forwarding to
|
||||||
// Example:
|
// original object's Call. Example:
|
||||||
//
|
//
|
||||||
// TEST(FooTest, RunsCallbackWithBarArgument) {
|
// TEST(FooTest, RunsCallbackWithBarArgument) {
|
||||||
// MockFunction<int(string)> callback;
|
// MockFunction<int(string)> callback;
|
||||||
// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
|
// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
|
||||||
// Foo(callback.AsStdFunction());
|
// Foo(callback.AsStdFunction());
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// The internal::SignatureOfT<F> indirection allows to use other types
|
||||||
|
// than just function signature type. This is typically useful when
|
||||||
|
// providing a mock for a predefined std::function type. Example:
|
||||||
|
//
|
||||||
|
// using FilterPredicate = std::function<bool(string)>;
|
||||||
|
// void MyFilterAlgorithm(FilterPredicate predicate);
|
||||||
|
//
|
||||||
|
// TEST(FooTest, FilterPredicateAlwaysAccepts) {
|
||||||
|
// MockFunction<FilterPredicate> predicateMock;
|
||||||
|
// EXPECT_CALL(predicateMock, Call(_)).WillRepeatedly(Return(true));
|
||||||
|
// MyFilterAlgorithm(predicateMock.AsStdFunction());
|
||||||
|
// }
|
||||||
template <typename F>
|
template <typename F>
|
||||||
class MockFunction;
|
class MockFunction : public internal::MockFunction<internal::SignatureOfT<F>> {
|
||||||
|
using Base = internal::MockFunction<internal::SignatureOfT<F>>;
|
||||||
template <typename R, typename... Args>
|
|
||||||
class MockFunction<R(Args...)> {
|
|
||||||
public:
|
public:
|
||||||
MockFunction() {}
|
using Base::Base;
|
||||||
MockFunction(const MockFunction&) = delete;
|
|
||||||
MockFunction& operator=(const MockFunction&) = delete;
|
|
||||||
|
|
||||||
std::function<R(Args...)> AsStdFunction() {
|
|
||||||
return [this](Args... args) -> R {
|
|
||||||
return this->Call(std::forward<Args>(args)...);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation detail: the expansion of the MOCK_METHOD macro.
|
|
||||||
R Call(Args... args) {
|
|
||||||
mock_.SetOwnerAndName(this, "Call");
|
|
||||||
return mock_.Invoke(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal::MockSpec<R(Args...)> gmock_Call(Matcher<Args>... m) {
|
|
||||||
mock_.RegisterOwner(this);
|
|
||||||
return mock_.With(std::move(m)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal::MockSpec<R(Args...)> gmock_Call(const internal::WithoutMatchers&,
|
|
||||||
R (*)(Args...)) {
|
|
||||||
return this->gmock_Call(::testing::A<Args>()...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
internal::FunctionMocker<R(Args...)> mock_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The style guide prohibits "using" statements in a namespace scope
|
// The style guide prohibits "using" statements in a namespace scope
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
# include <objbase.h>
|
# include <objbase.h>
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -802,12 +803,30 @@ using MockMethodMockFunctionSignatureTypes = Types<
|
|||||||
>;
|
>;
|
||||||
TYPED_TEST_SUITE(MockMethodMockFunctionSignatureTest, MockMethodMockFunctionSignatureTypes);
|
TYPED_TEST_SUITE(MockMethodMockFunctionSignatureTest, MockMethodMockFunctionSignatureTypes);
|
||||||
|
|
||||||
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionTemplateArgumentDeduced) {
|
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionTemplateArgumentDeducedForRawSignature) {
|
||||||
using Argument = TypeParam;
|
using Argument = TypeParam;
|
||||||
MockFunction<Argument> foo;
|
MockFunction<Argument> foo;
|
||||||
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<Argument>(foo));
|
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<Argument>(foo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionTemplateArgumentDeducedForStdFunction) {
|
||||||
|
using Argument = std::function<TypeParam>;
|
||||||
|
MockFunction<Argument> foo;
|
||||||
|
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<Argument>(foo));
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionAsStdFunctionMethodSignatureTheSameForRawSignatureAndStdFunction) {
|
||||||
|
using ForRawSignature = decltype(&MockFunction<TypeParam>::AsStdFunction);
|
||||||
|
using ForStdFunction = decltype(&MockFunction<std::function<TypeParam>>::AsStdFunction);
|
||||||
|
EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct MockMethodSizes0 {
|
struct MockMethodSizes0 {
|
||||||
MOCK_METHOD(void, func, ());
|
MOCK_METHOD(void, func, ());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user