Gmock - Check that a method is not called with a particular argument - unit-testing

There is a method with one string parameter virtual void method(const std::string& str) = 0;
In some cases, I need to be sure that this method is not called with a specific argument, for example, "321".
If the method is called somewhere as ifce->method("123"); and in tests I do EXPECT_CALL(mock, method("321")).Times(0); then the test fails:
Expected arg #0: is equal to "321"
Actual: "123"
Expected: to be never called
Actual: never called - saturated and active
[ FAILED ] test.invokeMethodWithDiferentParameters (0 ms)
How to do it correctly?

Either use testing::NiceMock, which ignores all uninteresting calls
NiceMock<MockFoo> mock;
EXPECT_CALL(mock, method("321")).Times(0);
Or add several expectations
EXPECT_CALL(mock, method(_)).Times(AtLeast(1));
EXPECT_CALL(mock, method("321")).Times(0);

Related

Is it possible to depend expected calls in gMock together?

Assume that I want to test following function:
template<typename Pack>
bool is_valid(const Pack& pack) {
if (pack.a() > 0)
return pack.b();
return false;
};
I will write a small mocker for Pack as follows:
class PackMock {
public:
MOCK_METHOD(int, a, (), (const));
MOCK_METHOD(bool, b, (), (const));
};
and now I try to write test this method with in test function:
TEST(MyTests, IsValidTest) {
PackMock p;
EXPECT_CALL(p, a())
.WillOnce(Return(0))
.WillOnce(Return(1))
.WillOnce(Return(20));
EXPECT_CALL(p, b())
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_FALSE(is_valid(p));
EXPECT_FALSE(is_valid(p));
EXPECT_TRUE(is_valid(p));
}
At the first sight, this code should be OK. I have 3 expectation and my mocker returns 3 different set of values and this is what happens in real application running (data-wise).
But if you run this code, you will get error that mocker expectations is not satisfied (it says that b() is expected to call 3 times while it is called twice). The reason is that when first test happens, a() returns 0, and because of if condition, b() is not called at all. So at the end, everything is messed up.
Now I wonder if there is a way to for example connect these expectations together or I should always set my expectations based on how code works rather than how my data works? I personally think that the later should be correct. For example, if a() in mocker called we make sure that at we always satisfy 1 expectation in b()? or for example we chain these expectations together in a way that b() is expected only if a() > 0?
Firstly, you can use a testing::Sequence instance to keep track of mock calls in sequence. You can also directly define a InSequence for the test as in the docs.
Secondly, your first EXPECT_CALL does not call the b() mock call, because a() returns 0 which then never evaluates the return pack.b().
As an example found here, I've indicated how you can use a Sequence class in your example as follows:
TEST(MyTests, IsValidTest) {
// Setup the mock object
PackMock p;
// Keep track of the sequence of events
// using a sequence class
testing::Sequence sequence;
// # First is_valid() - a
EXPECT_CALL(p, a())
.InSequence(sequence)
.WillOnce(Return(0));
// # First is_valid() - b - not called
// EXPECT_CALL(p, b())
// .InSequence(sequence)
// .WillOnce(Return(true));
// # Second is_valid() - a
EXPECT_CALL(p, a())
.InSequence(sequence)
.WillOnce(Return(1));
// # Second is_valid() - b
EXPECT_CALL(p, b())
.InSequence(sequence)
.WillOnce(Return(false));
// # Third is_valid() - a
EXPECT_CALL(p, a())
.InSequence(sequence)
.WillOnce(Return(20));
// # Third is_valid() - b
EXPECT_CALL(p, b())
.InSequence(sequence)
.WillOnce(Return(true));
// Act - Initiate the calls and inject the
// mock object as a dependency
// # First call - a() returns 0,
// thus returns false (but() b is not called)
EXPECT_FALSE(is_valid(p));
// # Second call - a() returns 1,
// thus returns false, because b returns false
EXPECT_FALSE(is_valid(p));
// # Third call - a() returns 20,
// thus returns true, because b returns true
EXPECT_TRUE(is_valid(p));
}
This will provide the following output:
Running main() from /opt/compiler-explorer/libs/googletest/release-1.10.0/googletest/src/gtest_main.cc
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from MyTests
[ RUN ] MyTests.IsValidTest
[ OK ] MyTests.IsValidTest (0 ms)
[----------] 1 test from MyTests (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
Thus, to answer your question:
Is it possible to depend expected calls in gMock together?
Yes, using a testing::Sequence class with or just using testing::InSequence()
Thus, if you have calls depending on each other in your test, use a sequence class instance(s) to link them.

Mocked object not passing to the other class

I'm making a mock class of istream to test a class. But the mocked object is not passing to the actual class i want to use in.
This is the mock class.
class MockStream{
private:
std::string filename_;
public:
MockStream(){
}
MockStream(std::string filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out):filename_(filename){
}
MockStream(const MockStream &a){}
MockStream& operator=(const MockStream& a){
return *this;
}
~MockStream(){}
MOCK_CONST_METHOD0(is_open,bool());
MOCK_METHOD0(close,void());
MOCK_METHOD2(read,MockStream&(char*,std::streamsize));
MOCK_METHOD2(write,MockStream&(const char*,std::streamsize));
MOCK_METHOD2(seekg,MockStream&(std::streamoff,std::ios_base::seekdir));
MOCK_METHOD1(seekg,MockStream&(std::streampos));
MOCK_METHOD0(get_filename,std::string());
};
test:
TEST(random_access_stack, mocked_test)
{
RandomAccessStack<TestClass,u_int64_t,MockStream> stack;
MockStream mocked;
EXPECT_CALL(mocked,is_open()).Times(1).WillOnce(testing::Return(true));
stack.SetStream(mocked);
EXPECT_TRUE(stack.is_open());
}
SetStream function:
void SetStream(STREAM& handle){
file_handle_ = handle;
}
where file_handle_ is of type MockStream passed by template
The output is:
GMOCK WARNING:
Uninteresting mock function call - returning default value.
Function call: is_open()
Returns: false
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#knowing-when-to-expect for details.
/build/libs/storage/tests/gtest/random_access_stack_tests.cpp:79: Failure
Value of: stack.is_open()
Actual: false
Expected: true
/build/libs/storage/tests/gtest/random_access_stack_tests.cpp:73: Failure
Actual function call count doesn't match EXPECT_CALL(mocked, is_open())...
Expected: to be called once
Actual: never called - unsatisfied and active

Is it possible to make scoped expectations in Google Mock?

Is it possible to scope an expectation using Google Mock? In other words, let's say I have the following test fixture:
class Fixture : public testing::Test
{
public:
void SetUp();
void TearDown();
ObjectUnderTest testObject;
MockObject mock;
};
Now, in the SetUp() function, I want to allow a mock function call as many times as is necessary during initialisation:
void Fixture::SetUp()
{
EXPECT_CALL(mock.DoStuff(_)).Times(Any());
testObject.Initialise(mock);
}
After this, I want this particular expectation to go out-of-scope and any calls to DoStuff() to generate a failure. I can't use RetiresOnSaturation() because it will never saturate!
In other words, if I have the following test case:
TEST_F(Fixture, DoesWhatItsSupposedTo)
{
EXPECT_CALL(mock, DoStuff(Eq(3)));
testObject.DoSomething(mock);
}
I would like this to fail if DoSomething() calls DoStuff(4) on the mock object. With gmock default behaviour (which is right for most scenarios), it will first check the second expectation that won't match; it will then check the expectation in SetUp() that will match and pass.
Does anyone know if this is possible?
It may not be really answer to your question, but you can explicitly forbid a call using .Times(0):
TEST_F(Fixture, DoesWhatItsSupposedTo)
{
EXPECT_CALL(mock, DoStuff(Eq(3)));
EXPECT_CALL(mock, DoStuff(Ne(3)))
.Times(0);
testObject.DoSomething(mock);
}
This will expect one call of DoStuff(3)and no other calls of DoStuff() within this test - any call is first checked against DoStuff(Ne(3)). Before the test, any call will still be accepted.

GoogleMock: how to expect precisely one call with a certain argument, and see diagnostic on failure?

Maybe a finesse question, my problem is that if I write:
EXPECT_CALL(mock, handleMessage(_)).Times(0); // expectation #1
EXPECT_CALL(mock, handleMessage(Pointee(IsLike(aSpecificMessage)))); // expectation #2
... and method handleMessage is called once, but with a different argument (not aSpecificMessage), then the failure looks like:
Mock function called more times than expected - returning default value.
Function call: handleMessage(0x8b5378)
Returns: false
Expected: to be never called
Actual: called once - over-saturated and active
Google Mock doesn't print the diagnostic on why the argument didn't match the predicate in expectation #2.
This is presumably because expectation #1 is the first to fail (?).
If I omit expectation #1, then the failure is verbose, along the lines of:
Google Mock tried the following 1 expectation, but it didn't match:
../../test/Test.cpp:143: EXPECT_CALL(mock, handleMessage(Pointee(IsLike(aSpecificMessage))))...
Expected arg #0: points to a value that <....>
Actual: 0xfeaf18, which points to <.....>
I'm using a custom Matcher IsLike and I went through the trouble of generating very explicit mismatch reasons, I'd like them to be printed. I also would not want to give up expectation #1 because that goes in a "default" section and by default I want no calls on that mock throughout the rest of the tests.
Looks like you should use the StrictMock template modifier. Let's use this simple class and mock:
struct Foo
{
virtual void function(int) {
}
};
struct MockFoo: public Foo
{
MOCK_METHOD1(function, void(int x));
};
Let's start with a basic test that exercises that method:
TEST(MockTest, basic_one_expectation)
{
MockFoo foo;
EXPECT_CALL(foo, function(4));
Foo& foo1(foo);
foo1.function(3);
}
Output:
[ RUN ] MockTest.basic_one_expectation
unknown file: Failure
Unexpected mock function call - returning directly.
Function call: function(3)
Google Mock tried the following 1 expectation, but it didn't match:
mock-test.cpp:298: EXPECT_CALL(foo, function(4))...
Expected arg #0: is equal to 4
Actual: 3
Expected: to be called once
Actual: never called - unsatisfied and active
mock-test.cpp:298: Failure
Actual function call count doesn't match EXPECT_CALL(foo, function(4))...
Expected: to be called once
Actual: never called - unsatisfied and active
[ FAILED ] MockTest.basic_one_expectation (1 ms)
That's one of the alternatives you've already considered, but you don't want it because you have other tests that don't have any particular expectations about whether the function is called, and you want those tests to fail if the function gets called anyway. As a reminder, let's see what happened when we try such a test:
TEST(MockTest, basic_no_expectation)
{
MockFoo foo;
Foo& foo1(foo);
foo1.function(3);
}
Output:
[ RUN ] MockTest.basic_no_expectation
GMOCK WARNING:
Uninteresting mock function call - returning directly.
Function call: function(3)
Stack trace:
[ OK ] MockTest.basic_no_expectation (1 ms)
We get a warning, but the test still passes. That's no good for you. Let's see what effect StrictMock has:
TEST(MockTest, strict_no_expectation)
{
::testing::StrictMock<MockFoo> foo;
Foo& foo1(foo);
foo1.function(3);
}
Output:
[ RUN ] MockTest.strict_no_expectation
unknown file: Failure
Uninteresting mock function call - returning directly.
Function call: function(3)
[ FAILED ] MockTest.strict_no_expectation (0 ms)
We didn't have to explicitly say that we don't want the function to be called, but when the function gets called anyway, the test correctly fails. Exactly what you wanted.
Finally, let's look at what happens with StrictMock in the case where there are explicit expectations for the function's argument:
TEST(MockTest, strict_one_expectation)
{
::testing::StrictMock<MockFoo> foo;
EXPECT_CALL(foo, function(4));
Foo& foo1(foo);
foo1.function(3);
}
Output:
[ RUN ] MockTest.strict_one_expectation
unknown file: Failure
Unexpected mock function call - returning directly.
Function call: function(3)
Google Mock tried the following 1 expectation, but it didn't match:
mock-test.cpp:307: EXPECT_CALL(foo, function(4))...
Expected arg #0: is equal to 4
Actual: 3
Expected: to be called once
Actual: never called - unsatisfied and active
mock-test.cpp:307: Failure
Actual function call count doesn't match EXPECT_CALL(foo, function(4))...
Expected: to be called once
Actual: never called - unsatisfied and active
[ FAILED ] MockTest.strict_one_expectation (0 ms)
The diagnostics show the reason the argument didn't match, just like the original basic_one_expectation test shown above.

EasyMock andReturn() vs andStubReturn()

What is the difference between using andReturn(T value) vs andStubReturn(T value) for EasyMock?
In what situation would you use andStubReturn() where andReturn() can't achieve the same result?
You use a stub return for a method call on the mock that you expect to happen but aren't otherwise interested in. You use a regular return for a "regular" method call.
Consider the following method:
public void someMethod(String arg) {
if (logger.isDebugEnabled()) {
logger.debug("Calling doSomething() on service "
+ service.getName().hashCode());
}
service.postMessage("{" + arg + "}");
if (logger.isDebugEnabled()) {
logger.info("Finished calling doSomething() on service "
+ service.getName().hashCode());
}
}
...where service is a mockable field. The hashCode() thing in the log statements is contrived, but the point is that your mock needs to respond to any number of calls to getName() to avoid an NPE, while you couldn't otherwise care less about it.
When writing an EasyMock based unit test for this method, you'd andStubReturn() the call to getName() and use a normal andReturn() for the call to postMessage(String). When you verify the mock object, it'll only consider the latter and your the test doesn't break if you change the log4j config.
An additional note for clarity.
If you use .andStubReturn() (or if you use .andReturn(foo).anyTimes()), there will be no minimum expected call count. So if you set a mock expectation using either of these two, and the mocked method is NOT called, the .verify() call will not assert.
Example that will NOT assert when the mocked method isn't called;
FooClass myFooClass = EasyMock.createNiceMock(FooClass.class);
EasyMock.expect(myFooClass.someMethod(EasyMock.anyInt()).andStubReturn(true);
EasyMock.replay(myFooClass);
EasyMock.verify(myFooClass);
Example that WILL assert when the mocked method isn't called;
FooClass myFooClass = EasyMock.createNiceMock(FooClass.class);
EasyMock.expect(myFooClass.someMethod(EasyMock.anyInt()).andReturn(true).atLeastOnce();
EasyMock.replay(myFooClass);
EasyMock.verify(myFooClass);