Makes googlemock throw a runtime_error instead of abort when a mock
method with no default value is invoked (if exceptions are enabled).
This commit is contained in:
parent
cf40604cf0
commit
edd4ab4945
@ -66,6 +66,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
# include <stdexcept> // NOLINT
|
||||
#endif
|
||||
|
||||
#include "gmock/gmock-actions.h"
|
||||
#include "gmock/gmock-cardinalities.h"
|
||||
#include "gmock/gmock-matchers.h"
|
||||
@ -1425,10 +1429,12 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Performs the default action of this mock function on the given arguments
|
||||
// and returns the result. Asserts with a helpful call descrption if there is
|
||||
// no valid return value. This method doesn't depend on the mutable state of
|
||||
// this object, and thus can be called concurrently without locking.
|
||||
// Performs the default action of this mock function on the given
|
||||
// arguments and returns the result. Asserts (or throws if
|
||||
// exceptions are enabled) with a helpful call descrption if there
|
||||
// is no valid return value. This method doesn't depend on the
|
||||
// mutable state of this object, and thus can be called concurrently
|
||||
// without locking.
|
||||
// L = *
|
||||
Result PerformDefaultAction(const ArgumentTuple& args,
|
||||
const string& call_description) const {
|
||||
@ -1437,9 +1443,16 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
||||
if (spec != NULL) {
|
||||
return spec->GetAction().Perform(args);
|
||||
}
|
||||
Assert(DefaultValue<Result>::Exists(), "", -1,
|
||||
call_description + "\n The mock function has no default action "
|
||||
"set, and its return type has no default value set.");
|
||||
const string message = call_description +
|
||||
"\n The mock function has no default action "
|
||||
"set, and its return type has no default value set.";
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
if (!DefaultValue<Result>::Exists()) {
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
#else
|
||||
Assert(DefaultValue<Result>::Exists(), "", -1, message);
|
||||
#endif
|
||||
return DefaultValue<Result>::Get();
|
||||
}
|
||||
|
||||
|
@ -634,15 +634,19 @@ TEST(DoDefaultTest, ReturnsBuiltInDefaultValueByDefault) {
|
||||
EXPECT_EQ(0, mock.IntFunc(true));
|
||||
}
|
||||
|
||||
// Tests that DoDefault() aborts the process when there is no built-in
|
||||
// default value for the return type.
|
||||
// Tests that DoDefault() throws (when exceptions are enabled) or aborts
|
||||
// the process when there is no built-in default value for the return type.
|
||||
TEST(DoDefaultDeathTest, DiesForUnknowType) {
|
||||
MockClass mock;
|
||||
EXPECT_CALL(mock, Foo())
|
||||
.WillRepeatedly(DoDefault());
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
EXPECT_ANY_THROW(mock.Foo());
|
||||
#else
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
mock.Foo();
|
||||
}, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Tests that using DoDefault() inside a composite action leads to a
|
||||
|
@ -1111,7 +1111,11 @@ TEST(UndefinedReturnValueTest, ReturnValueIsMandatory) {
|
||||
// TODO(wan@google.com): We should really verify the output message,
|
||||
// but we cannot yet due to that EXPECT_DEATH only captures stderr
|
||||
// while Google Mock logs to stdout.
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
EXPECT_ANY_THROW(a.ReturnResult(1));
|
||||
#else
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnResult(1), "");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Tests that an excessive call (one whose arguments match the
|
||||
@ -1260,87 +1264,116 @@ TEST(SequenceTest, AnyOrderIsOkByDefault) {
|
||||
|
||||
// Tests that the calls must be in strict order when a complete order
|
||||
// is specified.
|
||||
TEST(SequenceTest, CallsMustBeInStrictOrderWhenSaidSo) {
|
||||
TEST(SequenceTest, CallsMustBeInStrictOrderWhenSaidSo1) {
|
||||
MockA a;
|
||||
ON_CALL(a, ReturnResult(_))
|
||||
.WillByDefault(Return(Result()));
|
||||
|
||||
Sequence s;
|
||||
|
||||
EXPECT_CALL(a, ReturnResult(1))
|
||||
.InSequence(s)
|
||||
.WillOnce(Return(Result()));
|
||||
|
||||
.InSequence(s);
|
||||
EXPECT_CALL(a, ReturnResult(2))
|
||||
.InSequence(s)
|
||||
.WillOnce(Return(Result()));
|
||||
|
||||
.InSequence(s);
|
||||
EXPECT_CALL(a, ReturnResult(3))
|
||||
.InSequence(s)
|
||||
.WillOnce(Return(Result()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
a.ReturnResult(1);
|
||||
a.ReturnResult(3);
|
||||
a.ReturnResult(2);
|
||||
}, "");
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
a.ReturnResult(2);
|
||||
a.ReturnResult(1);
|
||||
a.ReturnResult(3);
|
||||
}, "");
|
||||
.InSequence(s);
|
||||
|
||||
a.ReturnResult(1);
|
||||
|
||||
// May only be called after a.ReturnResult(2).
|
||||
EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
|
||||
|
||||
a.ReturnResult(2);
|
||||
a.ReturnResult(3);
|
||||
}
|
||||
|
||||
// Tests specifying a DAG using multiple sequences.
|
||||
TEST(SequenceTest, CallsMustConformToSpecifiedDag) {
|
||||
// Tests that the calls must be in strict order when a complete order
|
||||
// is specified.
|
||||
TEST(SequenceTest, CallsMustBeInStrictOrderWhenSaidSo2) {
|
||||
MockA a;
|
||||
MockB b;
|
||||
Sequence x, y;
|
||||
ON_CALL(a, ReturnResult(_))
|
||||
.WillByDefault(Return(Result()));
|
||||
|
||||
Sequence s;
|
||||
EXPECT_CALL(a, ReturnResult(1))
|
||||
.InSequence(x)
|
||||
.WillOnce(Return(Result()));
|
||||
|
||||
EXPECT_CALL(b, DoB())
|
||||
.Times(2)
|
||||
.InSequence(y);
|
||||
|
||||
.InSequence(s);
|
||||
EXPECT_CALL(a, ReturnResult(2))
|
||||
.InSequence(x, y)
|
||||
.WillRepeatedly(Return(Result()));
|
||||
.InSequence(s);
|
||||
|
||||
EXPECT_CALL(a, ReturnResult(3))
|
||||
.InSequence(x)
|
||||
.WillOnce(Return(Result()));
|
||||
// May only be called after a.ReturnResult(1).
|
||||
EXPECT_NONFATAL_FAILURE(a.ReturnResult(2), "Unexpected mock function call");
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
a.ReturnResult(1);
|
||||
b.DoB();
|
||||
a.ReturnResult(2);
|
||||
}, "");
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
a.ReturnResult(2);
|
||||
}, "");
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
a.ReturnResult(3);
|
||||
}, "");
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
a.ReturnResult(1);
|
||||
b.DoB();
|
||||
b.DoB();
|
||||
a.ReturnResult(3);
|
||||
a.ReturnResult(2);
|
||||
}, "");
|
||||
|
||||
b.DoB();
|
||||
a.ReturnResult(1);
|
||||
b.DoB();
|
||||
a.ReturnResult(3);
|
||||
a.ReturnResult(2);
|
||||
}
|
||||
|
||||
// Tests specifying a DAG using multiple sequences.
|
||||
class PartialOrderTest : public testing::Test {
|
||||
protected:
|
||||
PartialOrderTest() {
|
||||
ON_CALL(a_, ReturnResult(_))
|
||||
.WillByDefault(Return(Result()));
|
||||
|
||||
// Specifies this partial ordering:
|
||||
//
|
||||
// a.ReturnResult(1) ==>
|
||||
// a.ReturnResult(2) * n ==> a.ReturnResult(3)
|
||||
// b.DoB() * 2 ==>
|
||||
Sequence x, y;
|
||||
EXPECT_CALL(a_, ReturnResult(1))
|
||||
.InSequence(x);
|
||||
EXPECT_CALL(b_, DoB())
|
||||
.Times(2)
|
||||
.InSequence(y);
|
||||
EXPECT_CALL(a_, ReturnResult(2))
|
||||
.Times(AnyNumber())
|
||||
.InSequence(x, y);
|
||||
EXPECT_CALL(a_, ReturnResult(3))
|
||||
.InSequence(x);
|
||||
}
|
||||
|
||||
MockA a_;
|
||||
MockB b_;
|
||||
};
|
||||
|
||||
TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag1) {
|
||||
a_.ReturnResult(1);
|
||||
b_.DoB();
|
||||
|
||||
// May only be called after the second DoB().
|
||||
EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
|
||||
|
||||
b_.DoB();
|
||||
a_.ReturnResult(3);
|
||||
}
|
||||
|
||||
TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag2) {
|
||||
// May only be called after ReturnResult(1).
|
||||
EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
|
||||
|
||||
a_.ReturnResult(1);
|
||||
b_.DoB();
|
||||
b_.DoB();
|
||||
a_.ReturnResult(3);
|
||||
}
|
||||
|
||||
TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag3) {
|
||||
// May only be called last.
|
||||
EXPECT_NONFATAL_FAILURE(a_.ReturnResult(3), "Unexpected mock function call");
|
||||
|
||||
a_.ReturnResult(1);
|
||||
b_.DoB();
|
||||
b_.DoB();
|
||||
a_.ReturnResult(3);
|
||||
}
|
||||
|
||||
TEST_F(PartialOrderTest, CallsMustConformToSpecifiedDag4) {
|
||||
a_.ReturnResult(1);
|
||||
b_.DoB();
|
||||
b_.DoB();
|
||||
a_.ReturnResult(3);
|
||||
|
||||
// May only be called before ReturnResult(3).
|
||||
EXPECT_NONFATAL_FAILURE(a_.ReturnResult(2), "Unexpected mock function call");
|
||||
}
|
||||
|
||||
TEST(SequenceTest, Retirement) {
|
||||
@ -1530,71 +1563,112 @@ TEST(AfterTest, SucceedsWhenTotalOrderIsSatisfied) {
|
||||
a.DoA(2);
|
||||
}
|
||||
|
||||
// Calls must be in strict order when specified so.
|
||||
TEST(AfterDeathTest, CallsMustBeInStrictOrderWhenSpecifiedSo) {
|
||||
// Calls must be in strict order when specified so using .After().
|
||||
TEST(AfterTest, CallsMustBeInStrictOrderWhenSpecifiedSo1) {
|
||||
MockA a;
|
||||
MockB b;
|
||||
|
||||
// Define ordering:
|
||||
// a.DoA(1) ==> b.DoB() ==> a.DoA(2)
|
||||
Expectation e1 = EXPECT_CALL(a, DoA(1));
|
||||
Expectation e2 = EXPECT_CALL(b, DoB())
|
||||
.After(e1);
|
||||
EXPECT_CALL(a, DoA(2))
|
||||
.After(e2);
|
||||
|
||||
a.DoA(1);
|
||||
|
||||
// May only be called after DoB().
|
||||
EXPECT_NONFATAL_FAILURE(a.DoA(2), "Unexpected mock function call");
|
||||
|
||||
b.DoB();
|
||||
a.DoA(2);
|
||||
}
|
||||
|
||||
// Calls must be in strict order when specified so using .After().
|
||||
TEST(AfterTest, CallsMustBeInStrictOrderWhenSpecifiedSo2) {
|
||||
MockA a;
|
||||
MockB b;
|
||||
|
||||
// Define ordering:
|
||||
// a.DoA(1) ==> b.DoB() * 2 ==> a.DoA(2)
|
||||
Expectation e1 = EXPECT_CALL(a, DoA(1));
|
||||
Expectation e2 = EXPECT_CALL(b, DoB())
|
||||
.Times(2)
|
||||
.After(e1);
|
||||
EXPECT_CALL(a, ReturnResult(2))
|
||||
.After(e2)
|
||||
.WillOnce(Return(Result()));
|
||||
EXPECT_CALL(a, DoA(2))
|
||||
.After(e2);
|
||||
|
||||
a.DoA(1);
|
||||
// If a call to ReturnResult() violates the specified order, no
|
||||
// matching expectation will be found, and thus the default action
|
||||
// will be done. Since the return type of ReturnResult() is not a
|
||||
// built-in type, gmock won't know what to return and will thus
|
||||
// abort the program. Therefore a death test can tell us whether
|
||||
// gmock catches the order violation correctly.
|
||||
//
|
||||
// gtest and gmock print messages to stdout, which isn't captured by
|
||||
// death tests. Therefore we have to match with an empty regular
|
||||
// expression in all the EXPECT_DEATH()s.
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnResult(2), "");
|
||||
b.DoB();
|
||||
|
||||
// May only be called after the second DoB().
|
||||
EXPECT_NONFATAL_FAILURE(a.DoA(2), "Unexpected mock function call");
|
||||
|
||||
b.DoB();
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnResult(2), "");
|
||||
|
||||
b.DoB();
|
||||
a.ReturnResult(2);
|
||||
a.DoA(2);
|
||||
}
|
||||
|
||||
// Calls must satisfy the partial order when specified so.
|
||||
TEST(AfterDeathTest, CallsMustSatisfyPartialOrderWhenSpecifiedSo) {
|
||||
TEST(AfterTest, CallsMustSatisfyPartialOrderWhenSpecifiedSo) {
|
||||
MockA a;
|
||||
ON_CALL(a, ReturnResult(_))
|
||||
.WillByDefault(Return(Result()));
|
||||
|
||||
// Define ordering:
|
||||
// a.DoA(1) ==>
|
||||
// a.DoA(2) ==> a.ReturnResult(3)
|
||||
Expectation e = EXPECT_CALL(a, DoA(1));
|
||||
const ExpectationSet es = EXPECT_CALL(a, DoA(2));
|
||||
EXPECT_CALL(a, ReturnResult(3))
|
||||
.After(e, es)
|
||||
.WillOnce(Return(Result()));
|
||||
.After(e, es);
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnResult(3), "");
|
||||
// May only be called last.
|
||||
EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
|
||||
|
||||
a.DoA(2);
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnResult(3), "");
|
||||
|
||||
a.DoA(1);
|
||||
a.ReturnResult(3);
|
||||
}
|
||||
|
||||
// Calls must satisfy the partial order when specified so.
|
||||
TEST(AfterTest, CallsMustSatisfyPartialOrderWhenSpecifiedSo2) {
|
||||
MockA a;
|
||||
|
||||
// Define ordering:
|
||||
// a.DoA(1) ==>
|
||||
// a.DoA(2) ==> a.DoA(3)
|
||||
Expectation e = EXPECT_CALL(a, DoA(1));
|
||||
const ExpectationSet es = EXPECT_CALL(a, DoA(2));
|
||||
EXPECT_CALL(a, DoA(3))
|
||||
.After(e, es);
|
||||
|
||||
a.DoA(2);
|
||||
|
||||
// May only be called last.
|
||||
EXPECT_NONFATAL_FAILURE(a.DoA(3), "Unexpected mock function call");
|
||||
|
||||
a.DoA(1);
|
||||
a.DoA(3);
|
||||
}
|
||||
|
||||
// .After() can be combined with .InSequence().
|
||||
TEST(AfterDeathTest, CanBeUsedWithInSequence) {
|
||||
TEST(AfterTest, CanBeUsedWithInSequence) {
|
||||
MockA a;
|
||||
Sequence s;
|
||||
Expectation e = EXPECT_CALL(a, DoA(1));
|
||||
EXPECT_CALL(a, DoA(2)).InSequence(s);
|
||||
EXPECT_CALL(a, ReturnResult(3))
|
||||
.InSequence(s).After(e)
|
||||
.WillOnce(Return(Result()));
|
||||
EXPECT_CALL(a, DoA(3))
|
||||
.InSequence(s)
|
||||
.After(e);
|
||||
|
||||
a.DoA(1);
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnResult(3), "");
|
||||
|
||||
// May only be after DoA(2).
|
||||
EXPECT_NONFATAL_FAILURE(a.DoA(3), "Unexpected mock function call");
|
||||
|
||||
a.DoA(2);
|
||||
a.ReturnResult(3);
|
||||
a.DoA(3);
|
||||
}
|
||||
|
||||
// .After() can be called multiple times.
|
||||
@ -1636,17 +1710,24 @@ TEST(AfterTest, AcceptsUpToFiveArguments) {
|
||||
// .After() allows input to contain duplicated Expectations.
|
||||
TEST(AfterTest, AcceptsDuplicatedInput) {
|
||||
MockA a;
|
||||
ON_CALL(a, ReturnResult(_))
|
||||
.WillByDefault(Return(Result()));
|
||||
|
||||
// Define ordering:
|
||||
// DoA(1) ==>
|
||||
// DoA(2) ==> ReturnResult(3)
|
||||
Expectation e1 = EXPECT_CALL(a, DoA(1));
|
||||
Expectation e2 = EXPECT_CALL(a, DoA(2));
|
||||
ExpectationSet es;
|
||||
es += e1;
|
||||
es += e2;
|
||||
EXPECT_CALL(a, ReturnResult(3))
|
||||
.After(e1, e2, es, e1)
|
||||
.WillOnce(Return(Result()));
|
||||
.After(e1, e2, es, e1);
|
||||
|
||||
a.DoA(1);
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnResult(3), "");
|
||||
|
||||
// May only be after DoA(2).
|
||||
EXPECT_NONFATAL_FAILURE(a.ReturnResult(3), "Unexpected mock function call");
|
||||
|
||||
a.DoA(2);
|
||||
a.ReturnResult(3);
|
||||
|
78
test/gmock_ex_test.cc
Normal file
78
test/gmock_ex_test.cc
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2013, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: wan@google.com (Zhanyong Wan)
|
||||
|
||||
// Tests Google Mock's functionality that depends on exceptions.
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using testing::HasSubstr;
|
||||
using testing::internal::GoogleTestFailureException;
|
||||
|
||||
// A user-defined class.
|
||||
class Something {};
|
||||
|
||||
class MockFoo {
|
||||
public:
|
||||
// A mock method that returns a user-defined type. Google Mock
|
||||
// doesn't know what the default value for this type is.
|
||||
MOCK_METHOD0(GetSomething, Something());
|
||||
};
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
||||
TEST(DefaultValueTest, ThrowsRuntimeErrorWhenNoDefaultValue) {
|
||||
MockFoo mock;
|
||||
try {
|
||||
// No expectation is set on this method, so Google Mock must
|
||||
// return the default value. However, since Google Mock knows
|
||||
// nothing about the return type, it doesn't know what to return,
|
||||
// and has to throw (when exceptions are enabled) or abort
|
||||
// (otherwise).
|
||||
mock.GetSomething();
|
||||
FAIL() << "GetSomething()'s return type has no default value, "
|
||||
<< "so Google Mock should have thrown.";
|
||||
} catch (const GoogleTestFailureException& /* unused */) {
|
||||
FAIL() << "Google Test does not try to catch an exception of type "
|
||||
<< "GoogleTestFailureException, which is used for reporting "
|
||||
<< "a failure to other testing frameworks. Google Mock should "
|
||||
<< "not throw a GoogleTestFailureException as it will kill the "
|
||||
<< "entire test program instead of just the current TEST.";
|
||||
} catch (const std::exception& ex) {
|
||||
EXPECT_THAT(ex.what(), HasSubstr("has no default value"));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // unnamed namespace
|
Loading…
Reference in New Issue
Block a user