EasyMock missing behavior even though it's defined - java

No matter what I do, I get the following error when trying to mock a method
java.lang.IllegalStateException: missing behavior definition for the preceding method call:
ConfigurationSection.get("country-language")
Usage is: expect(a.foo()).andXXX()
My code for testing:
EasyMock.expect(section.getString("country-language")).andReturn("US");
LocaleManager.updateLocale(section, Collections.emptyList());
EasyMock.expectLastCall();
replayAll();
Assert.assertEquals("Test", TranslatedMessage.translate("test"));
verifyAll();
The expect andReturn is called for the mocked class, and the static upateLocale method calls the method, first thing.
The strange thing is this test works fine:
EasyMock.expect(section.getString("country-language")).andReturn("US");
replayAll();
Assert.assertEquals("US", section.getString("country-language"));
verifyAll();
But calling it from an external method doesn't work.

Your mock says:
EasyMock.expect(section.getString("country-language"))
The error says:
ConfigurationSection.get("country-language")
You are not mocking get("country-language"). You are mocking getString("country-language").
Unrelated, but verify is a maintenance nightmare and should generally be avoided. This ties test code directly to an implementation. Tests should focus on inputs and outputs if at all possible.

Related

Mockito throws UnnecessaryStubbingException for stub defined in generic #BeforeEach setup method

I have a unit test class where my unit under test is dependent on another class. The dependency is mocked using Mockito and then setup with a generic stub that's run before every unit test, using JUnit's #BeforeEach annotation. See the below pseudo-code.
#ExtendWith(MockitoExtension.class)
public class FooFactoryTest {
#Mock
private BarDependency barDependency;
#InjectMocks
private FooFactory unitUnderTest;
#BeforeEach
public void setup() {
when(barDependency.leftBar(any())).thenReturn(new Bar());
when(barDependency.rightBar(any())).thenReturn(new Bar());
}
... many tests ...
This setup works perfectly for 9 of my 10 unit tests. Unfortunately one of my tests is failing with the following error:
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
1. -> at nl.devillers.mockito.FooFactoryTest.setup(FooFactoryTest.java:69)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
Now, I understand the error and why it's thrown, because in that specific test my unit under test short-circuits early and doesn't hit all the stubs that have been setup. I'm aware there's a lenient option in Mockito, but that'll disable the check for the entire class/project.
My question is: how do I disable this strictness for one specific unit test?
Again: I do not want to disable the strictness at the class or project level, since I think it's valuable check. I also do not want to move my setup code to the tests that do need the stubs, because then I have to duplicate the setup code nine times. In this case I just want to disable or skip the check for this specific test.
You can avoid this check at the test-level by resetting the mock with the stub that's not being called. This is a bit of a work around, but it'll allow you to pass your test without having to make the mock lenient for your entire test class or removing the mock entirely from your setup method.
To reset your barDependency mock, add the following line of code to the end of your test that is failing with a UnnecessaryStubbingException.
Mockito.reset(barDependency);
If none of the stubs on barDependency are being used, you can also place this line at the beginning of your test with your other arrangements, which is a little cleaner. Or alternately, put it at the top of your test method and then setup the stubs you do need. This essentially overrides whatever is being setup in your generic setup method.
You can also use lenient in the code of your #BeforeEach, like this:
#BeforeEach
public void setup() {
lenient().when(barDependency.leftBar(any())).thenReturn(new Bar());
lenient().when(barDependency.rightBar(any())).thenReturn(new Bar());
}
This should not be necessary, based on this doc in the UnnecessaryStubbingException:
Mockito JUnit Runner triggers UnnecessaryStubbingException only when none of the test methods use the stubbings. This means that it is ok to put default stubbing in a 'setup' method or in test class constructor. That default stubbing needs to be used at least once by one of the test methods.

Do I always need `when/thenReturn` for mock object's functions

I am writing a test in Scala where I do something like this --
val svc = mock[Service]
Initializer.fun1(svc)
fun1 internally calls a function svc.fun2 which returns Unit.
My test is failing when it tries to execute svc.fun2 with this error -
java.lang.NoSuchMethodError: org.mockito.internal.invocation.ArgumentsProcessor.expandArgs
As svc has already been mocked, I shouldn't have to mock fun2 ,right ?
Unless I want fun2 to return a specific value
Same thing worked for another codebase of mine, but that's using a different library for Mockito
Update :
I also tried adding a when/thenReturn for fun2 but still getting the same error.
I just did this
when(svc.fun2()) thenReturn()
since it's supposed to return UNIT

Mock a Method with complex type

While mocking a method, which have complex type, returning null in java
public void sendRequest(OnlineRequest request) {
OnlineResponse response = client.handleRequest(request);
System.out.println( response);
}
Mockito.when(client.handleRequest(request)).thenReturn(new OnlineResponse());
If I understand correctly, your issue is that System.out.println(response); prints null?
This is most likely due to the fact that client.handleRequest() is not being called with the request you expect. This may be an error somewhere in code you haven't provided us, OR it may simply be due to the fact that OnlineRequest does not have an implementation of equals/hash-code, so when() is never triggered because it is not called with the exact same instance of OnlineRequest as you use in your unit tests.
You might wish to test that handleRequest is called with exactly the object you expect. This can be accomplished using verify():
verify(client).handleRequest(request);
in your unit test. This too is dependent on the equals/hash-code implementation to determine whether request is the expected parameter or not.

best solution for mocking chained calls in Java

I have the following code:
handler = NodeHandler.getINodeHandler(localZone).getITspPlatformHandler().getITspProcessorManagementHandler();
I mocked this out this way:
mockStatic(NodeHandler.class);
INodeHandler iNodeHandler = mock(INodeHandler.class,Mockito.RETURNS_DEEP_STUBS);
when(NodeHandler.getINodeHandler(localZone)).thenReturn(iNodeHandler);
ITspProcessorManagementHandler iTspProcessorManagementHandler =mock(ITspProcessorManagementHandler.class,Mockito.RETURNS_DEEP_STUBS);
when(iNodeHandler.getITspPlatformHandler().getITspProcessorManagementHandler()).thenReturn(iTspProcessorManagementHandler);
After a few row of code an another chained method call comes:
ITspTrafficProcessor processor = NodeHandler.getINodeHandler(localZone, localUI).getITspPlatformHandler().getITspProcessorManagementHandler()
.getITspProcessorHandler(procs[i]).getITspTrafficProcessorHandler(0).getAttributes();
And i mocked this out this way:
when(NodeHandler.getINodeHandler(localZone,UI.CORBA)).thenReturn(iNodeHandler);
when(iNodeHandler.getITspPlatformHandler().getITspProcessorManagementHandler()(+1+).getITspProcessorHandler(anyString())
.getITspTrafficProcessorHandler(anyInt()).getAttributes()).thenReturn(null);
So my question is that, i can not find a better solution than this, because the problem is if i tell the mockito to return null to the handler instead of iTspProcessorManagementHandler then i get a nullpointer exception at (+1+), but if i do the following changes to my code:
INodeHandler iNodeHandler = mock(INodeHandler.class,Mockito.RETURNS_MOCKS);
Than mockito mocks out every method call, and my when-thenReturn statements does not returns what i want for example null. So any advice to do a better solution????
Messy mocking like that is an indication that you could improve abstraction. I'd consider encapsulating that particular logic in a helper interface/class, or to inject the expected type returned by the "trainwreck" to the method/class.

EasyMock JUnit testing throws error on the setter method

I am using easyMock for JUnit testing. I want to test a method which gets a Project object as its arguments and sets the modify date of that project and persists it in db.
So e.g.
public void setProject(Project project) {
project.setModifyDate(new Date());
this.reporsitory.persist(project);
}
Now at my test method I have tow mocked projects. For one of them I have set the return value of the getModifyDate. For the other mocked project object I just call the setProject(mockedProject); Now I assertEqual these two project objects.
The problem is easymock throws me an error at the project.setModifyDate(new Date()) of the class which I am testing.
Exception : Unexpected method call project.setModifyDate(..).. Expected:1, Actual:0.
It seems that it does not expect the setter method. Could you please let me know what I am doing wrong.
Thanks.
Yes, it is because of the type of mock object you created. It expects your code to call every method you defined when the one call executes. I cannot remember the exact name but i think it is something like nicemock, versus a strictmock whick makes your code execute every expected method. You should use EasyMock.createNiceMock() for your mock object. The error you have is because it expects you to call setModifyDate but your code didn't for that call.
Your call is unexpected because you must have not put EasyMock.expected for that method. You need to add your mock object .expected(getMethod).andReturns(something).

Categories

Resources