Getting exception from EasyMock's "nice mock" with a debugger attached - java

(Disclaimer - EasyMock newb)
According to the documentation (and this post), if I wanted to use EasyMock to generate stub objects, I should use EasyMock.createNiceMock(). A "nice mock" is actually a stub - i.e an object that doesn't participate in validation, just returns values.
However, the following snippet fails for me with an IllegalStateException("missing behavior definition for the preceding method"), on the second foo.translate() line.
Foo foo = EasyMock.createNiceMock(Foo.class);
EasyMock.replay(foo); // added this line
foo.translate("a", "b");
foo.translate("a", "b"); // only the second calls throws an exception
Can anyone explain this, or rather tell me how to use EasyMock to create stubs with zero verbosity (o(number_of_exercised_mock_methods)).
Edit - I've noticed that I'm getting these errors almost always when a debugger is attached, but never when it isn't attached. Any idea how that may be related?

Complementing on Jeff's answer.
From EasyMock's method createNiceMock javadoc:
Creates a mock object that implements the given interface, order checking
is disabled by default, and the mock object will return 0,
null or false for unexpected invocations.
A mock object created by this method don't need any configuration (expected invocations). You just have to create it and "replay it". Example:
ComplicatedObject stub = EasyMock.createNiceMock();
replay(stub);
Any method call is allowed on the created stub (it won't throw an Exception), and they will always return the default value (0, null or false). If you set up an specific invocation expectation, then you'll have to configure it's return value or you'll get an error (that's your case).
If you want to restrict which methods can be executed (making the test fail if an unexpected method is called), them I'm afraid you'll have to create a regular mock, set up every invocation expectation and a return value for each of those.

If your translate method returns a value, you need to setup an expectation for it.
expect(foo.translate("a","b")).andStubReturn(retVal);

You need to call EasyMock.replay(foo). Before you do that your mock object is in a "record state". From EasyMock documentation:
In the record state (before calling
replay), the Mock Object does not
behave like a Mock Object, but it
records method calls. After calling
replay, it behaves like a Mock Object,
checking whether the expected method
calls are really done.
If you with to create a stub object just call createNiceMock followed by replay:
Foo foo = EasyMock.createNiceMock(Foo.class);
EasyMock.replay(foo);
foo.translate("a", "b");
foo.translate("a", "b");

Related

Mock - make a spy class method return a specific value

I'm running some unit tests on a methodA of a spied instance of a class (let's say instance is myClass), which uses a helper method (lets call it helper(long num, ObjectA obA, ObjectB obB)) to determine the boolean value of a flag
The parameters of this class are all mocked, the class is instantiated with a spy call, and the method itself is a protected method with 3 parameters. The method is called with every run of methodA. MethodA sets the values of the parameters for the helper method
My question is, is there a way to make, in this specific test, the helper method return true?
I've tried to, using the following:
when(myClass.shouldSetFlag(anyLong(), any(ObjectA.class), any(ObjectB.class))).thenReturn(true);
but every time I get a null pointer exception.
Would really appreciate some insight, thanks!
Since you've provided only one line of code and no stack trace, I assume the NullPointerException is thrown from the shouldSetFlag method.
When you mock the method using when(...) Mockito actually replaces the matchers with default values during the method call in this line (it's still Java code, the method is still called). If you act on ObjectA or ObjectB instances inside the method, the actual code encounters a null reference and the exception is thrown.
From the docs:
Matcher methods like anyObject(), eq() do not return matchers. Internally, they record a matcher on a stack and return a dummy value (usually null).
You can also observe that in the Mockito code, since it's open source.
To work around that use doReturn(...) (see the docs here) - the actual method will not be called while mocking, yet it still will be registered in Mockito.

Getting a null pointer exception when using when().thenreturn() in mockito

I am trying to stub this method: QueryUtils.toOrder(sort, root, builder)
and I am doing
when(QueryUtils.toOrder(any(Sort.class), any(Root.class), any(CriteriaBuilder.class)).thenReturn(mock(List.class));
but it goes into the queryUtils method body and it will say Sort is null and it will throw a NPE. But why would it need to go into the method body when it is a stub? I haven't had this issue before and I don't think it should care what the internal logic of the method is.
The Problem here is that Mockito cannot brake the Java language.
In the when(mockedObject.mockedMethod()).thenReturn() form the mocked method is executed and its return value is passed into the mock where Mockito exchanges it with the configured value. But the mocked object is initialized with nulls so any property of the mocked object that is accessed in the mocked method raises a NPE.
To come around you should use the slidely less readable form doReturn().when(mockObject).mockedMethod().
please notice the closing ) moved!
In this form Mockito prevents the execution of the mocked method by polymorphism entirely and directly returns the configured value.

EasyMock expectations with void methods

I'm using EasyMock to do some unit tests and I don't understand the usage of EasyMock.expectLastCall(). As you can see in my code below, I have an object with a method that returns void getting called in some other object's method. I would think that I have to make EasyMock expect that method call, but I tried commenting out the expectLastCall() invocation and it still works. Is it because I passed EasyMock.anyObject()) that it registered it as an expected call or is there something else going on?
MyObject obj = EasyMock.createMock(MyObject.class);
MySomething something = EasyMock.createMock(MySomething.class);
EasyMock.expect(obj.methodThatReturnsSomething()).andReturn(something);
obj.methodThatReturnsVoid(EasyMock.<String>anyObject());
// whether I comment this out or not, it works
EasyMock.expectLastCall();
EasyMock.replay(obj);
// This method calls the obj.methodThatReturnsVoid()
someOtherObject.method(obj);
The API doc for EasyMock says this about expectLastCall():
Returns the expectation setter for the last expected invocation in the current thread. This method is used for expected invocations on void methods.
This method returns you the handle of expectation through IExpectationSetters; which gives you ability to validate(assert) that your void method was called or not and related behaviors e.g.
EasyMock.expectLastCall().once();
EasyMock.expectLastCall().atLeastOnce();
EasyMock.expectLastCall().anyTimes();
Detailed API of the IExpectationSetters is here.
In your example you are just getting the handle and not doing anything with it hence you don't see any impact of having or removing the statement. It's very same as you call some getter method or declare some variable and don't use it.
You only need EasyMock.expectLastCall(); when you need to further verify anything other than "That the method was called. (same as setting expectation)"
Say you want to verify how many times the method was called so you will add any of :
EasyMock.expectLastCall().once();
EasyMock.expectLastCall().atLeastOnce();
EasyMock.expectLastCall().anyTimes();
Or say you want to throw an exception
EasyMock.expectLastCall().andThrow()
If you don't care then EasyMock.expectLastCall(); is not required and does not make any difference, your statement "obj.methodThatReturnsVoid(EasyMock.<String>anyObject());" is enough for setting up expectation.
You are missing EasyMock.verify(..)
MyObject obj = EasyMock.createMock(MyObject.class);
MySomething something = EasyMock.createMock(MySomething.class);
EasyMock.expect(obj.methodThatReturnsSomething()).andReturn(something);
obj.methodThatReturnsVoid(EasyMock.<String>anyObject());
// whether I comment this out or not, it works
EasyMock.expectLastCall();
EasyMock.replay(obj);
// This method calls the obj.methodThatReturnsVoid()
someOtherObject.method(obj);
// verify that your method was called
EasyMock.verify(obj);

How to stub get/set of simple types

I am new to Mockito and I was wondering how I could stub a get/set pair.
For example
public interface Order {
public short getStatus();
public void setStatus(short status);
}
How can I make them behave properly:
if somewhere in a test I invoke setStatus(4); I would like getStatus() to return 4. How can this be done?
Are you stubbing or mocking?
The difference is whether you are verifying behaviour or providing data for a test. You say:
if somewhere in a test I invoke setStatus(4); I would like getStatus() to return 4.
this implies both at the same time. You either want to verify that setStatus() was called with an argument 4.
verify(mockObject).setStatus(4);
or you want to set your mock object to return 4 when getStatus() is called.
when(mockObject.getStatus()).thenReturn(4);
Mockito has some tutorials which explain how to use it for each situation. I suspect you could do both in your test (but have not checked) but this would be a smell to me, as you should ideally only be checking mocking a single thing in your test, everything else should be stubbed. But, as ever, context is everything and so it may be that you need to stub one part of your object so you can verify the behaviour of another part, in which case it would be fine.
Follow the AAA syntax and arrange your test (ie do the setup and have the when clause) then act (ie call the method on the object under test) then do your asserts (ie have your verify statements)
EDIT
it seems that in the newer versions (1.8+) of mockito it may be possible to do what you want, although it is not recommended. You can use a Spy to create a partial mock of an object. In this case you should be able to create a Spy of your actual object, leave the getStatus() and setStatus() methods un-stubbed (so they are actually called and used) and just stub out the other methods (or just verify they were called presumably). You can read about it in section 13 Spying on real objects on this page.
You can set the behavior of the setStatus method so that it updates the behavior of the getStatus method, as follows:
Mockito.doAnswer(invocation -> {
short status = invocation.getArgumentAt(0, Short.class);
Mockito.when(mockOrder.getStatus()).thenReturn(status);
return null;
}).when(mockOrder).setStatus(Mockito.anyShort());

EasyMock Expectation with a void method and an object array as argument?

When using EasyMock to set expectations for a void method, is it possible to specify an Object array as one of the arguments for the method?
For example, if we have something like this:
Errors mockErrors = createMock(Errors.class);
...
mockErrors.rejectValue(Object[]{"5", "2"});
mockErrors.replay();
classUnderTest.someMethod();
whereby within ClassUnderTest, someMethod calls rejectValue(Object[]{"5", "2"});
However, despite the expectation being set to exactly what is being called, easy mock complains about an unexpected method call.
> Unexpected method call rejectValue(["5", "2"]):
> rejectValue(["5", "2"]): expected: 1, actual: 0
I presume that it's because under the hood it's relying on equals method on an Object[] and as the two are different it returns false and does not satisfy the condition.
Is there a way around it? As I'm not setting expectation using expect() I can use any()... is there a way of doing the same on a void method?
mockErrors.rejectValue(aryEq(new Object[] {"5", "2"}));
See the javadoc for details.

Categories