JMockit Partial mock - All methods except one - java

I'm new to JMockit and writing a test for a quite complex class, call it XYZ. In each #Test method, I want to call the corresponding real method of XYZ, but mock all (or sometimes nearly all) other methods, which should by verified afterwards. At the moment my first test method looks like this (I want to mock all methods except "start", so I'm using a regex):
#Test
public void testStart(#Mocked({ "^(start).*" }) XYZ xyz) {
new Expectations() {{
xyz.isValidState(); result = true;
}};
...
}
When I run the test, I get "java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter" (at the line where the first expectation is defined) which seems to say that the mocking did not work. Is my regex wrong or this there another problem?

That regex selects the methods that will be mocked. So, isValidState() does not get mocked, as it doesn't match the expression; hence JMockit says there was no mocked invocation at the point the "result" field is used.
There is no way to not mock just a single method in a class while mocking all others, except for using partial mocking with new Expectations(XYZ.class) and then recording expectations on all the methods that should be mocked. This, of course, would be cumbersome. Which is a good thing here, because partial mocking in general is not a feature to be used in "normal" cases; it's only for exceptional situations.
If you want to unit test a class, even a complex one, mocking should be restricted to its dependencies, and even then only those dependencies that you choose or need to regard as external to the unit under test. That said, if a given internally called method in XYZ gets in the way of a clean test, then you can exceptionally choose to "mock it out" through partial mocking; but that would usually mean a single method (or just a few) in class XYZ to be mocked per test.

Related

How do I get Mockito mocks to cause a failure when unexpected calls are made?

I have some mock objects that are probably going to get passed around a bit and might end up being fairly complex.
I'd like to either have Mockito output a log for each call made to a mock or I'd like it to fail whenever an unexpected call is made so I can iterate through those calls and set up appropriate responses.
How can I accomplish this?
The most-idiomatic way of doing this is with verifyNoMoreInteractions, as in Mockito docs #8:
//interactions
mock.doSomething();
mock.doSomethingUnexpected();
//verification
verify(mock).doSomething();
//following will fail because 'doSomethingUnexpected()' is unexpected
verifyNoMoreInteractions(mock);
I say "most-idiomatic" above because that method has its own warning label, which links to the blog post "Should I worry about the unexpected?" by Mockito originator Szczepan Faber.
verifyNoMoreInteractions() is not recommended to use in every test method. verifyNoMoreInteractions() is a handy assertion from the interaction testing toolkit. Use it only when it's relevant. Abusing it leads to overspecified, less maintainable tests.
In short, you should have a very clear reason to check what your dependency is not doing or what your system-under-test is not calling, as opposed to what they are doing and calling. You might use verifyNoMoreInteractions for an RPC object, if you want to avoid unnecessary RPC calls, but not (say) a calculator with no side effects. Even better is to specify your exact requirements with never() or times(int) as parameters to verify.
That said, there are two even-less-idiomatic ways of doing this:
You can take an overall log of calls made using mockingDetails(Object) and iterating through getInvocations(). That should reflectively give you a whole list of the invocations. I have a hard time imagining how this would be useful in a test, but it might be useful in cleaning up a nebulous or poorly-documented existing system.
You can make the mock's default action to throw an exception, which means that if anyone calls something that you haven't stubbed, the test will immediately fail.
// untested pseudocode
YourObject yourObject = Mockito.mock(YourObject.class, withSettings()
.defaultAnswer(invocation -> {
throw new UnsupportedOperationException(invocation.toString());
}));
Sure, that'd work, but you'd not only be violating one of Mockito's core principles (mocks are nice by default, using EasyMock's definition of "nice"), but you'd also force yourself to only stub using doVerb (doReturn, doAnswer, etc) because calls to when(yourObject.doAnything()) would necessarily throw that exception before the call to when would even run.
Developers who are familiar with Mockito would likely say that this exception-prone cure is worse than the disease, and may be useful only for temporarily diagnosing the most tangled legacy code.
I was just asking myself the same question and... The solution using ReturnsSmartNulls will return SmartNulls instead of null... So it is meaningful for non-void methods only right ? What about void methods, the ones having side effects ?
In my opinion, if you want to make sure that your test fails when a method of your mock is called without your explicit behavior definition of it (doXXX(...).when(...) mockito methods) you can initialize your mocks with a custom default answer that will throw an exception, or better... fail your test.
For example you can add the following class inside your test class (or outside if you intend to use it elsewhere, or even use a MockitoConfiguration class as previously mentionned depending on what you want):
static class FailAnswer implements Answer<Object> {
#Override
public Object answer(InvocationOnMock invocation) {
String methodName = invocation.getMethod().getName();
String className = invocation.getMethod().getDeclaringClass().getSimpleName();
return fail(String.format("%s#%s should not have been called", className, methodName));
}
}
Then init your mock with this fake answer in your setUp method :
#BeforeEach
void setUp() {
delegateService = mock(DelegateService.class, new FailAnswer());
classUnderTest = new ClassUnderTest(delegateService);
}
Unfortunately, this solution is not compatible with #Mock annotation which only takes native predefined answers from org.mockito.Answers enum as argument. So that forces you to manually init every mock, spy, captor within the setUp method (RIP MockitoAnnotations.initMocks(this))
Benefit :
you get rid of default behavior of mockito mocks, sometimes hidding unintentionnal uses of mocks for specifics use cases (does is really matter ?)
=> You must define everything you use (inside tests or tests fixtures)
=> you don't have to make verification to make sure your test have not invoked methods it shouldn't have.
Drawbacks :
This is an unusual usage of mockito, so this makes your test less affordable
You give up on MockitoAnnotations feature
As you override mockito default stubbing, you must use the stubbing form do().when() instead of when(...).do(....), the latter providing au type-checking unlike the former.
Warning : This solution doesn't garantee your mock is called, it just garantees that the method you don't stub won't be called. It doesn't come as replacement for counting methods invocations neither.
The best answer I found is to configure Mockito to return SmartNulls.
https://static.javadoc.io/org.mockito/mockito-core/2.6.9/org/mockito/Mockito.html#RETURNS_SMART_NULLS
This implementation can be helpful when working with legacy code. Unstubbed methods often return null. If your code uses the object returned by an unstubbed call you get a NullPointerException. This implementation of Answer returns SmartNull instead of null. SmartNull gives nicer exception message than NPE because it points out the line where unstubbed method was called. You just click on the stack trace.
You can do it by mock or by default (might cause problems with other frameworks like Spring).
Manually
Writer writerMock = mock(Writer.class, RETURNS_SMART_NULLS);
Annotation
#Mock(answer = Answers.RETURNS_SMART_NULLS)
Set as Global Default
Configuration class must be in exactly this package. This might lead to strange failures with Spring.
package org.mockito.configuration;
import org.mockito.internal.stubbing.defaultanswers.ReturnsSmartNulls;
import org.mockito.stubbing.Answer;
public class MockitoConfiguration extends DefaultMockitoConfiguration {
public Answer<Object> getDefaultAnswer() {
return new ReturnsSmartNulls();
}
}
See: https://solidsoft.wordpress.com/2012/07/02/beyond-the-mockito-refcard-part-1-a-better-error-message-on-npe-with-globally-configured-smartnull/
I had problems with SpringBootRepositories and #MockBean when enabling the global default:
java.lang.ClassCastException: org.mockito.codegen.Object$MockitoMock$191495750 cannot be cast to xxx.xxx.MyObject
Example of error output
org.junit.ComparisonFailure: expected:<[DataRecordType{id=null, name='SomeRecord', pathTemplate='SomeTemplate'}]> but was:<[SmartNull returned by this unstubbed method call on a mock: dataRecordTypeRepository bean.getById(1L);]>
If you are trying to track the flow, you can use Mockito verify to check if certain call has been made.
verify(yourMockedObject).yourMethod();
you can also use times to verify if certain call has to be made exactly some number of times.
verify(yourMockedObject, times(4)).yourMethod();
It is not a good practice to make your unit test complex. Try to test only small unit of your code at a time.

Unit testing method parameter verification best practice

What is the best practice for verifying a method call with complex parameters when unit testing?
Say I'm testing a function like this:
class ClassA {
ClassB dependency;
void someFunction(SomeInputForA input) {
// do some thing
dependency.anotherFunction(differentInput);
}
}
The two options that I can think of for verifying that someFunction calls anotherFunction with the proper input are:
A) do a verify on the mock of dependency for calling anotherFunction
unitUnderTest.dependency = mockClassB;
InputClass expectedDifferentInput = ... ;
verify(mockClassB).anotherFunction(expectedDifferentInput);
B) do an argument captor on the call of anotherFunction and assert the properties
unitUnderTest.dependency = mockClassB;
ArgumentCaptor<InputClass> captor = ArgumentCaptor.for(InputClass.class);
verify(mockClassB).anotherFunction(captor.capture());
InputClass capturedInput = captor.getValue();
assertEquals(value, capturedInput.param1);
// and more asserts afterwards
Is there a suggested path here? I'd lean towards the captor method because it feels more rigorous and is not relying on objects equals implementations being proper.
Thoughts?
Is differentInput computated off input?
If so then your B) is the better way to go as you are saying for Input A, you expect ClassA to change this to expectedDifferentInput and want to verify the delegating class (ClassB) is called. You are verifying the transformation of the input and delegating logic of ClassA.
If differentInput has no relation to input then you don't need to use the captor as really you are just checking delegation.
Any public caller to someFunction on ClassA shouldn't need to know about ClassB so it can be said both methods A) and B) are actually white box testing, in this case and so you might as well use the captors anyway. As you vary your input to someFunction, captors may also help you to identify edge cases if differentInput is computed off input.
You can always use matchers on the object passed into mockClassB.anotherFunction(). For example, if you want to compare fields on an object, you can write:
Matcher<YourClass> yourMatcher = Matchers.hasProperty("yourProperty", Matchers.equals(whatever));
verify(mockClassB).anotherFunction(argThat(yourMatcher));
I prefer this way, since you can share syntax for the when and the verify for the matchers and you can combine any combination of matchers. You just need to include the latest mockito and hamcrest libraries to get this to work.
I've used argument captors but VERY sparingly. The biggest issue you run into is that this route creates fragile unit tests. And no one is happy when they make a small change to a class and then find themselves struggling with unit tests in calling classes that shouldn't have been affected.
That being said, absolutely you have to eventually ensure that correct calls are made. But if you rely on an equals override working, then you are relying on that class having an equals method that works, and this is then part of that class's contract (and unit tested in that class) which is reasonable.
So that's why I'd vote for keeping it simple and just using verify. Same thing in the end, but your unit test is just less fragile.

Reuse expectations block several times in JMockit

I am writing test cases for a liferay portal in which I want to mock ActionRequest, ThemeDisplay kind of objects. I have tried with writing expectations in each test method.
Now I want to generalize the approach by creating a BaseTest class which provides me all expectations needed for each method so that I don't have to write it again in the all test classes.
For one class I have tried by writing expectations in #Before method. How can I use same in different classes?
For example I want to do following in several classes:
#Before
public void setUp() {
// All expectations which are required by each test methods
new Expectations() {{
themeDisplay.getPermissionChecker();
returns(permissionChecker);
actionRequest.getParameter("userId");
returns("111");
actionRequest.getParameter("userName");
returns("User1");
}};
}
Also is there a way to provide that whenever I call actionRequest.getParameter() it may return the specific value which I provide?
Any help will be appreciated.
Generally, what you want is to create named Expectations and Verifications subclasses to be reused from multiple test classes. Examples can be found in the documentation.
Note that mocked instances have to be passed in, when instantiating said subclasses.
Methods like getPermissionChecker(), however, usually don't need to be explicitly recorded, since a cascaded instance is going to be automatically returned as needed.
Mocking methods like getParameter, though, hints that perhaps it would be better to use real objects rather than mocks. Mocking isn't really meant for simple "getters", and this often indicates that you may be mocking too much.

Mockito Mocking a return value and verify it

I have this class and wants to create a mock to return and verify the return value "50":
QAService.java:
#Path("/QAService")
public class QAService {
#GET()
//#Path("/")
#Produces("text/plain")
public String getServiceInfo() {
return "50";
}
My understanding of mock by defintion is that I can create a fake object of an implementation class and mock functions yet to be developed so I can test the interface.
Still I am creating this test to test mocking without having an interface. How do I verify it?:
QAServiceTest.java:
public class QAServiceTest {
#Test
public void getserviceTest () {
QAService qasmock = mock(QAService.class);
when(qasmock.getServiceInfo()).thenReturn("50");
String expected = "50";
assertEquals(expected, qasmock.getServiceInfo());
}
}
Junit will only run methods annotated with #Test, so add it
#Test
public void getserviceTest () {
QAService qasmock = mock(QAService.class);
when(qasmock.getServiceInfo()).thenReturn("50");
String expected = "50";
assertEquals(expected, qasmock.getServiceInfo());
}
Also, you should verify() that your mock expectations actually happened.
verify(qasmock, times(1)).getServiceInfo();
Note that it seems like you want to test QAService, but you really aren't doing that here. You are simply testing a mock. That's not the same thing.
Create the QAService object yourself and use it.
Let's get a couple definitions straight, first:
A unit test is a brief bit of code you write to ensure that the system you've developed is behaving correctly. Unit tests are often created in a framework like JUnit, but do not need to be. For example, a unit test would assertEquals(5, calculator.add(2, 3)).
A mock is an imitation of a real system, which is often used in unit tests. Mocks are often created in frameworks like Mockito or EasyMock, but do not need to be. Mocks are a form of "test double"—the general term for code you substitute in place of your actual systems, for testing purposes—and Martin Fowler defines them more exactly in an article called "Mocks Aren't Stubs".
When writing a unit test, you're trying to test a single unit, which is often called the system under test or SUT for short. Each test will probably have a different system under test, and the point is that the code that you are testing in the test is your real, actual code, not any sort of mock or fake implementation.
In a complex application, your classes will probably need to collaborate with other classes that may or may not be written or tested, which are categorically known as dependencies. Any given class or system may have its own dependencies, and may be a dependency for other systems. Mocking frameworks are good for mocking those dependencies, not for mocking the system under test.
For your example, QAService is the main class you're writing (system under test), and QAServiceTest is the unit test for that system. No mocks are necessarily required.
Let's say that QAService depends on another class not yet written, called "StorageService". You don't necessarily want to wait for StorageService to work before writing QAService's tests, so instead of using a real StorageService you use a mock. Again, in the unit test called QAServiceTest, you use a real QAService and mock its dependency StorageService.
Even though you don't have StorageService written, you probably have some expectation about how QAService will use that class. Maybe you know that when you call storageService.store(qaRecord), it should return a numeric ID like 101. Even without the code working, you can create a Mockito mockStorageService, and prepare it like this:
when(mockStorageService.store(expectedQARecord)).thenReturn(101);
Now let's say that at the end of the test, you want to ensure that the method of QAService that you're testing will absolutely call storageService.delete(101). A Mockito mockStorageService would check that like this:
verify(mockStorageService).delete(101);
It is often unnecessary to verify statements you have made with when, because the test is unlikely to succeed unless the system under test calls the mock correctly to get that return value (101 here).
Now let's say that you've written another block of code called QAApplication, which you're testing in a unit test called QAApplicationTest, that depends on QAService. You may not have QAService finished or tested, and using a real QAService would require a StorageService, so instead you use mock QAService with a real QAApplication in your unit test called QAApplicationTest.
So, to sum up, a mock works within unit tests to mock the dependencies of the system under test. In your situation, QAServiceTest will not need a mock QAService, but may be used to mock the dependencies of QAService. If you do need a mock QAService, you'll need it when testing another class where QAService itself is a dependency.

unit test best practice for method with mocks in Mockito

Lets say we have method to test in class A that calls method from class B. To test it we created mock for B and then verify if it was called. Is verify(...) enough for unit test or I need assert actual result of tested method?
Below is simplified example to clarify my concern:
public class StringWriterATest {
StringWriterB b = mock(StringWriterB.class);
#Test
public void stringWriterATest() {
StringBuffer sb = new StringBuffer();
StringWriterA a = new StringWriterA();
a.stringWriterB=b;
a.append(sb);
ArgumentCaptor<StringBuffer> argument = ArgumentCaptor.forClass(StringBuffer.class);
verify(b).append(argument.capture());
assertEquals("StringWriterA", ((StringBuffer)argument.getValue()).toString());
//do we really need this or above is enough for proper unit test of method a.append(sb);
//assertEquals("StringWriterA_StringWriterB", sb);
}
}
public class StringWriterA {
public StringWriterB stringWriterB;
public void append(StringBuffer sb) {
sb.append("StringWriterA");
stringWriterB.append(sb);
}
}
class StringWriterB {
public void append(StringBuffer sb) {
sb.append("StringWriterB");
}
}
Regards,
Max
There is never a need to mock a return value and verify an object at the same time.
Consider this:
StringWriterA is the class under test. Therefore you'll definitely want to use assertions to verify the behavior of this class. In order to do this, you mock out a dependency, StringWriterB.
You do not want to test StringWriterB in your test of StringWriterA, therefore any assertions of StringWriterB interactions in your test are in the wrong place.
You must assume that StringWriterB is behaving as expected. You either want to verify that StringWriterA called StringWriterB correctly (using verify()) or you want to mock its expected behavior and mock the return values.
If you mock, then the verify is implicit since the mocked return value will not be returned if the method is not called.
In your case, StringWriterA.append() does not return any value, so only a verify is even possible. That StringWriterB.append() also works should have a similar verify test in a stringWriterBTest of its own.
Note: It's nice to be explicit with tests. Since test methods are never called outside of a framework, there is never a need to type them out, so you can have much longer method names than in production code methods. A nice convention is:
<underTest>Should<Expected>[When]<Condition>()
i.e.
stringWriterAShouldAppendConstantAndDelegateToStringWriterB()
stringWriterAShouldThrowNullPointerExceptionWhenNullArgument()
When you have test failures in your build (continuous integration), then you don't have to hunt down what went wrong, the method name appears right by the failure and you can read it to know exactly what behavior must be fixed.
In your example, StringWriterB stores no state and the append method could easily be static. In that case then the call is purely a side effect and does not need to be tested.
However, I suspect your real code is much more complex. If there is a of another object accessing StringWriterB then you maye want to mock it out in case there are unexpected calls to it. You also may want to add the verify of B if you expect it to be expanded in the future -- possibly storing state from the append call and having accessors.
One thing to consider is what the purpose of the call to StringWriterA.append() is. If it's job is to append the string StringWriterAStringWriterB then that is what you should be testing and a mock is not necessary. How StringWriterA accomplishes that task is immaterial. If, however, part of its job is to also call the StringWriterB.append() method then a mock may will be necessary unless you want to test StringWriterB in A's test.
My rule of thumb WRT mocks is to use real objects until the wiring for the objects I'm not directly testing gets too hairy or too brittle. If I feel like a good portion of my tests are in actuality testing other objects then mocks would be a good idea.
First of all try to show somebody the test you wrote. It is hard to read in my opinion. You can't really tell from it what behaviour you are testing. A brief intro for you how to make it a bit more readable can be found here How to Write Clean, Testable Code .
Using argument captors is also a smell. Some examples how to avoid it can be found on this tdd blog.
To answer you question, verify is used to verify interactions between classes. It is used to drive the design of your code. The result (if needed) should be specified by a when or given at the beginning of your test.
Further information how to drive your design with mocks (when, given, verify, ...) and how mocks are different to stubs can be found here: Mocks are not stubs. That example uses JMock not Mockito for defining mocks, but it is very similar (it is about the concepts, not the details of implementation and libraries you use).

Categories

Resources