Leaked Google Mock Object Does not Fail - c++

I came across some odd behavior when mocking a c++ destructor, as documented in google mock cookbook. The class and mock are as follows:
// System under test
class Base {
public:
virtual ~Base(){};
};
// Mocked class
class MockBase : public Base {
public:
MOCK_METHOD0(Die, void());
virtual ~MockBase() { Die(); }
};
Test 1. Test that a mock object is destructed once. This test passes just fine.
// Test 1.
MockBase * mb1 = new MockBase();
EXPECT_CALL(*mb1, Die()).Times(1);
delete mb1;
Test 2. Expecting an object to be destructed twice, fails. This also makes sense.
// Test 2. This fails -> ok.
MockBase * mb2 = new MockBase();
EXPECT_CALL(*mb2, Die()).Times(2);
delete mb2;
Test 3. Testing that a non-deleted object is destructed. This test does not seem to fail, even though I expected it to fail. (notice that I commented out the delete command). At the end of the program, there are warnings that some mocked objects are never deleted.
// Test 3. This does not fail
MockBase * mb3 = new MockBase();
EXPECT_CALL(*mb3, Die()).Times(1);
//delete mb3;
Test 4. Testing that a non-deleted object is destructed twice. This test does not seem to fail either. Similar to test 3, I didn't delete this mockBase either, so I'd expect this to fail as well. I even increased the number of times that I expect this to be called, but it still doesn't fail.
// This does not fail
MockBase * mb4 = new MockBase();
EXPECT_CALL(*mb4, Die()).Times(2);
//delete mb4;
Can someone explain why Tests 3 and 4 pass?

From the Google Mock Cheat Sheet:
Google Mock will verify the expectations on a mock object when it is destructed, or you can do it earlier
In other words, Test 3 and 4 in your examples never have their expectations verified because the mock object doesn't get destroyed. As per the Cheat Sheet, you can force the expectations to be verified manually. For example, Test 3 becomes the following:
MockBase * mb3 = new MockBase();
EXPECT_CALL(*mb3, Die());
Mock::VerifyAndClearExpectations(mb3);

Related

UnitTC using Mock in C# is failing with error : actual and expected value are different

I have few test cases in my project, which all are failing with same reason.
There is one Mock class containing a list and a function which append value in the list.
My TC performs below action:
creates a new object of Mock class.
also creates some mock environment for the TC.
calls a function.
check Assert.
Assert is verifying the value and size of the List from Mock class object.
Now my 5 TC is failing with error in remote saying actual value is 100+ while expected is 1. But same TC is successful in local.
Mock class is
internal sealed class testMocks : IDisposable
{
private readonly IDisposable shimctxt = ShimContext.Create()
public testMocks()
{
ClassAImplementingShimBase.classBStatic.param1= this.appendToList
}
public List testList{get;} = new List()
public void Dispose(){
this.shimctxt.Dispose();
}
private bool appendToList(a,b)
{
this.testList.Add(new T()
{
val1=a
val2=b
});
return true;
}
}
T is another public sealed class
If I run only 1 failing TC commenting out other 4, it runs successfully.
I'm not able to understand how same mock object can be shared among these 5 TC, logically after 1 TC ends scope of the mock object should also end, but here size of List is increasing for all these 5 TC.
Also sometimes 1 TC fails other 4 are successful.
If I comment out 1 failing, another TC from earlier successful list fails with same error.
I'm not able to understand if error is in TC really or Mock class, or somewhere else.

Spock - How to work with repeated interactions

For few test cases I'm trying to follow a DRY principle, where only the interactions are different with same test case conditions. I'm not able to find a way to implement multiple methods in the interaction { } block.
As mentioned in http://spockframework.org/spock/docs/1.3/interaction_based_testing.html#_explicit_interaction_blocks, I'm using interaction { } in the then: block like below:
Java Code:
// legacy code (still running on EJB 1.0 framework, and no dependency injection involved)
// can't alter java code base
public voidGetData() {
DataService ds = new DataService();
ds = ds.findByOffset(5);
Long len = ds.getOffset() // happy path scenario; missing a null check
// other code
}
// other varieties of same code:
public voidGetData2() {
ItemEJB tmpItem = new ItemEJB();
ItemEJB item = tmpItem.findByOffset(5);
if(null != item) {
Long len = item.getOffset();
// other code
}
}
public voidGetData3() {
ItemEJB item = new ItemEJB().findByOffset(5);
if(null != item) {
Long len = item.getOffset();
// other code
}
}
Spock Test:
def "test scene1"() {
given: "a task"
// other code ommitted
DataService mockObj = Mock(DataService)
when: "take action"
// code omitted
then: "action response"
interaction {
verifyNoDataScenario() // How to add verifyErrorScenario() interaction to the list?
}
}
private verifyDataScenario() {
1 * mockObj.findByOffset(5) >> mockObj // the findByOffset() returns an object, so mapped to same mock instance
1 * mockObj.getOffset() >> 200
}
private verifyErrorScenario() {
1 * mockObj.findByOffset(5) >> null // the findByOffset() returns null
0 * mockObj.getOffset() >> 200 // this won't be executed, and should ie expected to throw NPE
}
The interaction closure doesn't accept more than one method call. I'm not sure if it's design limitation. I believe more can be done in the closure than just mentioning the method name. I also tried interpolating the mockObj as a variable and use data pipe / data table, but since it's referring the same mock instance, it's not working. I'll post that as a separate question.
I ended up repeating the test case twice just to invoke different interaction methods. Down the line I see more scenarios, and wanted to avoid copy & paste approach. Appreciate any pointers to achieve this.
Update:
Modified shared java code as the earlier DataService name was confusing.
As there's no DI involved, and I didn't find a way to mock method variables, so I mock them using PowerMockito, e.g. PowerMockito.whenNew(DataService.class).withNoArguments().thenReturn(mockObj)
Your application code looks very strange. Is the programming style in your legacy application really that bad? First a DataService object is created with a no-arguments constructor, just to be overwritten in the next step by calling a method on that instance which again returns a DataService object. What kind of programmer creates code like that? Or did you just make up some pseudo code which does not have much in common with your real application? Please explain.
As for your test code, it also does not make sense because you instantiate DataService mockObj as a local variable in your feature method (test method), which means that in your helper method mockObj cannot be accessed. So either you need to pass the object as a parameter to the helper methods or you need to make it a field in your test class.
Last, but not least, your local mock object is never injected into the class under test because, as I said in the first paragraph, the DataService object in getData() is also a local variable. Unless your application code is compeletely fake, there is no way to inject the mock because getData() does not have any method parameter and the DataService object is not a field which could be set via setter method or constructor. Thus, you can create as many mocks as you want, the application will never have any knowledge of them. So your stubbing findByOffset(long offset) (why don't you show the code of that method?) has no effect whatsoever.
Bottom line: Please provide an example reflecting the structure of your real code, both application and test code. The snippets you provide do not make any sense, unfortunately. I am trying to help, but like this I cannot.
Update:
In my comments I mentioned refactoring your legacy code for testability by adding a constructor, setter method or an overloaded getData method with an additional parameter. Here is an example of what I mean:
Dummy helper class:
package de.scrum_master.stackoverflow.q58470315;
public class DataService {
private long offset;
public DataService(long offset) {
this.offset = offset;
}
public DataService() {}
public DataService findByOffset(long offset) {
return new DataService(offset);
}
public long getOffset() {
return offset;
}
#Override
public String toString() {
return "DataService{" +
"offset=" + offset +
'}';
}
}
Subject under test:
Let me add a private DataService member with a setter in order to make the object injectable. I am also adding a check if the ds member has been injected or not. If not, the code will behave like before in production and create a new object by itself.
package de.scrum_master.stackoverflow.q58470315;
public class ToBeTestedWithInteractions {
private DataService ds;
public void setDataService(DataService ds) {
this.ds = ds;
}
// legacy code; can't alter
public void getData() {
if (ds == null)
ds = new DataService();
ds = ds.findByOffset(5);
Long len = ds.getOffset();
}
}
Spock test:
Now let us test both the normal and the error scenario. Actually I think you should break it down into two smaller feature methods, but as you seem to wish to test everything (IMO too much) in one method, you can also do that via two distinct pairs of when-then blocks. You do not need to explicitly declare any interaction blocks in order to do so.
package de.scrum_master.stackoverflow.q58470315
import spock.lang.Specification
class RepeatedInteractionsTest extends Specification {
def "test scene1"() {
given: "subject under test with injected mock"
ToBeTestedWithInteractions subjectUnderTest = new ToBeTestedWithInteractions()
DataService dataService = Mock()
subjectUnderTest.dataService = dataService
when: "getting data"
subjectUnderTest.getData()
then: "no error, normal return values"
noExceptionThrown()
1 * dataService.findByOffset(5) >> dataService
1 * dataService.getOffset() >> 200
when: "getting data"
subjectUnderTest.getData()
then: "NPE, only first method called"
thrown NullPointerException
1 * dataService.findByOffset(5) >> null
0 * dataService.getOffset()
}
}
Please also note that testing for exceptions thrown or not thrown adds value to the test, the interaction testing just checks internal legacy code behaviour, which has little to no value.

Why does Mockito "when" work on a non-mock object?

I recently saw some Mockito 1.9.5 code that worked like this:
MyObject myObject = new MyObject();
...
Mockito.when(myObject.someMethod()).thenReturn("bogus");
Since myObject is not a mock object, but is an instance of a non-mocked class, I was surprised this compiled and ran without failing the unit test. I expected I would get a failure saying something like "You asked me to set up an expectation on a non-mock object, and I expected to set expectations only on mock objects."
Why doesn't this code cause a test failure?
Update: adding more code that is necessary to actually replicate the behavior I find confusing. These examples fully illustrate my question. The following code behaves as I expected--when I run this test the test fails with a message that
when() requires an argument which has to be 'a method call on a mock'.
public class AnotherObject{
public String doSomething(){
return "did something";
};
}
public class MyObject{
private AnotherObject anotherObject = new AnotherObject();
public void setAnotherObject(AnotherObject anotherObject) {
this.anotherObject = anotherObject;
}
public String someMethod(){
return anotherObject.doSomething();
}
}
#Test
public void WhyDoesWhenWorkOnNonMock() throws Exception {
MyObject myObject = new MyObject();
Mockito.when(myObject.someMethod()).thenReturn("bogus");
}
Now if I add a couple specific lines to this contrived test, the test no longer fails even though I expected the same failure and same message as before:
public class AnotherObject{
public String doSomething(){
return "did something";
};
}
public class MyObject{
private AnotherObject anotherObject = new AnotherObject();
public void setAnotherObject(AnotherObject anotherObject) {
this.anotherObject = anotherObject;
}
public String someMethod(){
return anotherObject.doSomething();
}
}
#Test
public void WhyDoesWhenWorkOnNonMock() throws Exception {
MyObject myObject = new MyObject();
AnotherObject mockAnotherObject = Mockito.mock(AnotherObject.class);
myObject.setAnotherObject(mockAnotherObject);
Mockito.when(myObject.someMethod()).thenReturn("bogus");
}
By incredible and fragile coincidence, probably, unless myObject was actually set to be a spy.
Mockito allows for the creation of a "spy" of a real object:
MyObject myObject = spy(new MyObject());
Mockito.when(myObject.someMethod()).thenReturn("something");
// myObject is actually a duplicate of myObject, where all the fields are copied
// and the methods overridden. By default, Mockito silently records interactions.
myObject.foo(1);
verify(myObject).foo(anyInt());
// You can stub in a similar way, though doReturn is preferred over thenReturn
// to avoid calling the actual method in question.
doReturn(42).when(myObject).bar();
assertEquals(42, myObject.bar());
Barring that, this code is probably not working the way it looks like it should. when's parameter is meaningless, and is sugar meant to hide that the mocked interaction is the most recent method call to a mock. For example:
SomeObject thisIsAMock = mock(SomeObject.class);
OtherObject notAMock = new OtherObject();
thisIsAMock.methodOne();
Mockito.when(notAMock.someOtherMethod()).thenReturn("bar");
// Because notAMock isn't a mock, Mockito can't see it, so the stubbed interaction
// is the call to methodOne above. Now methodOne will try to return "bar",
// even if it isn't supposed to return a String at all!
Mismatches like this can be easy sources of ClassCastException, InvalidUseOfMatchersException, and other bizarre errors. It's also possible that your real MyObject class takes a mock as a parameter, and that last interaction is with a mock that someMethod interacts with.
Your edit confirms my suspicions. As far as Java is concerned, it needs to evaluate the parameter to when before it can invoke when, so your test calls someMethod (real). Mockito can't see that—it can only take action when you interact with one of its mocks—so in your first example it sees zero interactions with mocks and thus it fails. In your second example your someMethod calls doSomething, which Mockito can see, so it returns the default value (null) and marks that as the most recent method call. Then the call to when(null) happens, Mockito ignores the parameter (null) and refers to the most recently called method (doSomething), and stubs that to return "bogus" from that point on.
You can see that by adding this assertion to your test, even though you never stubbed it explicitly:
assertEquals("bogus", mockAnotherObject.doSomething());
For an additional reference, I wrote a separate SO answer on Mockito matchers, for which the implementation details might be useful. See steps 5 and 6 for an expanded view of a similar problem.

How to use thenAnswer with method which returns void

I want to unit test following method
public void addRecord(Record record)
{
Myclass newObj = new Mycalss();
// It creates newObj object, set some values using record object.
// and it adds the newObj in daatbase.
dataReqDao.persist(newObj);
}
I have mocked dataReqDao.persist method but how can I verify if right values are copied into newObj object? I want to get the newObj object.
I think thenAnswer will be the appropraite method to retrieve newObj ie method arguments but dont know how to use it method which returns void.
Update:
I tried
doAnswer(new Answer<Myclass>() {
public Myclass answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
return (Myclass)args[0];
}
}).when(dataReqDao.persist(any(Myclass.class)));
EDIT:
It should be (Thanks David)
doAnswer(new Answer<Myclass>() {
public Myclass answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
return (Myclass)args[0];
}
}).when(dataReqDao).persist(any(Myclass.class));
You can create a custom argument matcher that would check fields of that object, or use an argument captor to capture the object for further inspection.
For example, as follows:
ArgumentCaptor<Myclass> c = ArgumentCaptor.forClass(Myclass.class);
verify(dateReqDao).persist(c.capture());
Myclass newObj = c.getValue();
... // Validate newObj
You need to make it with thenAnswer (or then which i personally prefer), so you can assert/verify the values at the time of method call, in the method.
when(dataReqDao.persist(newObj)).then(new Answer<Void>() {
#Override
public Void answer(final InvocationOnMock invocation) {
Myclass newObjActual = (Myclass) invocation.getArguments()[0];
// Control
assertEquals(..., newObjActual.getX());
assertEquals(..., newObjActual.getY());
return null;
}
});
// Run Test
x.addRecord(record);
Here is a detail explanation: https://akcasoy.wordpress.com/2015/04/09/the-power-of-thenanswer/ (Use case 2)
ArgumentCaptor does not test in a clever way. When you change your method like this:
public void addRecord(Record record)
{
Myclass newObj = new Mycalss();
dataReqDao.persist(newObj);
// first persist, than set attributes
newObj.setX(..);
}
.. your test with Captor still runs, but it should fail. Since the ArgumentCaptor does not capture that state of the object at the time of call, but just the objectId, it does not matter for captor whether you set your attributes before or after dao call. Yet a good test should fail with every functional change. Here is my article exactly about this case:
https://akcasoy.wordpress.com/2015/02/03/how-to-ensure-quality-of-junit-tests/ (the above stubbing with the then is a better approach though than the one with InOrder approach)
Myclass newObj = new Myclass();
That line troubles me. If you are using dependency injection, you should have your factory send you an instance of that object. Then, when you create your unit tests, you can have the test factory send in a mock instance of MyClass which the unit test can also have access to. Then you can use axtavt's captor to see if it really did what it was supposed to do. There's nothing wrong with the unit test the way you did it, it's just that any() is kind of weak given that you know it is passing in an object of that type--what you want to know in the test is whether the object is the one you intended and has not been modified.

How to mock a method which also belongs to the target class itself?

Let's say we are testing a class C which has 2 methods M1 and M2 where M1 calls M2 when executed.
Testing M2 is ok, but how can we test M1? The difficulty is that we need to mock M2 if I'm not misunderstanding things.
If so, how can we mock another method while testing a method defined in the same class?
[Edit]
Class C has no base classes.
You can do this by setting the CallBase property on the mock to true.
For example, if I have this class:
public class Foo
{
public virtual string MethodA()
{
return "A";
}
public virtual string MethodB()
{
return MethodA() + "B";
}
}
I can setup MethodA and call MethodB:
[Fact]
public void RunTest()
{
Mock<Foo> mockFoo = new Mock<Foo>();
mockFoo.Setup(x => x.MethodA()).Returns("Mock");
mockFoo.CallBase = true;
string result = mockFoo.Object.MethodB();
Assert.Equal("MockB", result);
}
You should let the call to M1 pass through to a real instance of the M2 method.
In general, you should be testing the black box behaviour of your classes. Your tests shouldn't care that M1 happens to call M2 - this is an implementation detail.
This isn't the same as mocking external dependencies (which you should do)...
For example, say I have a class like this:
class AccountMerger
{
public AccountMerger(IAccountDao dao)
{
this.dao = dao;
}
public void Merge(Account first, Account second, MergeStrategy strategy)
{
// merge logic goes here...
// [...]
dao.Save(first);
dao.Save(second);
}
public void Merge(Account first, Account second)
{
Merge(first, second, MergeStrategy.Default);
}
private readonly IAccountDao dao;
}
I want my tests to show that:
Calling Merge(first, second, strategy) results in two accounts getting saved that have been merged using the supplied rule.
Calling Merge(first, second) results in two accounts getting saved that have been merged using the default rule.
Note that both of these requirements are phrased in terms of inputs and effects - in particular, I don't care how the class achieves these results, as long as it does.
The fact that the second method happens to use the first isn't something I care about, or even that I want to enforce - if I do so, I'll write very brittle tests. (There's even an argument that if you've messed about with the object under test using a mocking framework, you're not even testing the original object any more, so what are you testing?) This is an internal dependency that could quite happily change without breaking the requirements:
// ...
// refactored AccountMerger methods
// these still work, and still fulfil the two requirements above
public void Merge(Account first, Account second, MergeStrategy strategy)
{
MergeAndSave(first, second, strategy ?? MergeStrategy.Default);
}
public void Merge(Account first, Account second)
{
// note this no longer calls the other Merge() method
MergeAndSave(first, second, MergeStrategy.Default);
}
private void MergeAndSave(Account first, Account second, MergeStrategy strategy)
{
// merge logic goes here...
// [...]
dao.Save(first);
dao.Save(second);
}
// ...
As long as my tests only check inputs and effects, I can easily make this kind of refactoring - my tests will even help me to do so, as they make sure I haven't broken the class while making changes.
On the other hand, I do about the AccountMerger using the IAccountDao to save accounts following a merge (although the AccountMerger shouldn't care about the implementation of the DAO, only that it has a Save() method.) This DAO is a prime candidate for mocking - an external dependency of the AccountMerger class, feeling an effect I want to check for certain inputs.
You shouldn't mock methods in the target class, you should only mock external dependencies.
If it seems to make sense to mock M2 while testing M1 it often means that your class is doing too many things. Consider splitting the class and keeping M2 in one class and move M1 to a higher level class, which would use the class containing M2. Then mocking M2 is easy, and your code will actually become better.