Unit Testing Lambda Expressions - unit-testing

I have a method that is shown as below and this in turn call multiple private methods, that I won't be posting here.
#Bean
public CommandLineRunner registerStartersAndReaders(final Vertx vertx, final SpringVerticleFactory springVerticleFactory,
final SpringUtil springUtil, final GslConfig gslConfig) {
return args -> {
// Scan all the beans annotated with the #ElasticsearchBatchDataListener annotation.
List<Pair<Object, Method>> listenerMethods = springUtil.getListenerMethods();
// Deploy the starters per listener.
deployVerticle(listenerMethods, jsonConfig -> deployStarterVerticle(vertx, springVerticleFactory, jsonConfig), config);
// Deploy the reader verticles.
deployVerticle(listenerMethods, jsonConfig -> deployReaderVerticle(vertx, springVerticleFactory, jsonConfig), config);
setupTriggers(vertx, listenerMethods, config);
};
}
Then I have a test method for it :
#Test
public void registerStartersAndReadersTest() {
when(springUtil.getListenerMethods()).thenReturn(value);
CommandLineRunner runner = config.registerStartersAndReaders(vertx, springVerticleFactory, springUtil, config);
assertNotNull(runner);
}
Here, all the parameters passed into the method call are mocks. The problem is, when I run this test, it passes but it returns the value without getting into the private methods as it just returns 'args'.
Can someone please guide me, as to how I can make my test cover all the possible code. I am not supposed to change my code for the test.

I think you got confused with the lamba expression, and believe me it is very confusing in the beginning. But once you are fluent with it, it will be a breeze.
So here you got the instance of CommandLineRunner from method registerStartersAndReaders call, and your assertNotNull PASS as you have the not null instance, but until you call the run method of FunctionalInterface nothing will be executed.
Add runner.run(args) to execute the method(s) in your test case.

Related

Flink Job Testing with MiniClusterWithClientResource

I've wrote a #Test method in order to test the execuction of a Flink job.
This is the method:
#Test
void testFlinkJob() throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(2);
MyJob.buildJob(env, new MySourceFunction(), new MySinkFunction());
env.execute();
//asserts
}
Implementations details of MyJob.buildJob(), MySourceFunction and MySinkFunction are not important. Please, focus on env.setParallelism(2).
If I run this test, everything is ok. Fine!
However, Flink official documentation (https://nightlies.apache.org/flink/flink-docs-release-1.14/docs/dev/datastream/testing/#junit-rule-miniclusterwithclientresource), speaks about MiniClusterWithClientResource .
So I added these snippet to my test class, as showed into documentation.
#ClassRule
public static MiniClusterWithClientResource flinkCluster =
new MiniClusterWithClientResource(
new MiniClusterResourceConfiguration.Builder()
.setNumberSlotsPerTaskManager(2)
.setNumberTaskManagers(1)
.build());
I run my test again and it still passes. Perfect!
Then I started to play with the above snippet. The first thing I changed is the value of setNumberSlotsPerTaskManager() param from 2 to 1.
I launched a one more time my test. This time I expected a test failure because the value of parallelism (2) is higher than the value numberOfTaskManager * numberSlotPerTestManagers (1).
Instead, my test continues to pass.
Same thing if I write setNumberTaskManagers(0) (No TaskManager). Test continues to pass.
Seems that MiniClusterWithClientResource is dummy. Can you help my to understand how it work, please?
If you are working with JUnit 5, #ClassRule annotation will be ignored. You need to use extensions:
#ExtendWith(MiniClusterExtension.class)
public class MyTest {
#RegisterExtension
public static final MiniClusterExtension MINI_CLUSTER_RESOURCE = new MiniClusterExtension(
new MiniClusterResourceConfiguration.Builder()
.setNumberSlotsPerTaskManager(2)
.setNumberTaskManagers(1)
.build());
}
P.S.: MiniClusterExtension.class is still marked as #Experimental as of v1.16 and therefore subject to changes.

Mockito Stubbing not working after an exception is stubbed

So, I am trying to unit test a class in various scenarios. We use JUnit V 4.
I have a setUp method wherein i reStub the mock to return an expected mock Value.
I have 4 tests : test1-test4. test1,test2 work fine with the expected mocked value configured in perTestSetup method.
Test t3 needs MockClass to throw an exception, so i configure it seperately in t3. Now t3 works fine as the mock throws the exception as expected.
But when perTestSetup tries to reset the mock to return mockResult before running test4, it fails and throws the same Runtime exception configured in t4. I also tried reset() before mocking in perTestSetup(). But that too fails similarly.
What am i missing here?
#Before
public void perTestSetup(){
when(MockClass.functionCall(...)).thenReturn(mockResult);
}
#Test
public void test1(){
}
#Test
public void test2(){
}
#Test
public void test3(){
when(MockClass.functionCall(...)).thenThrow(new RuntimeExcption());
...
}
#Test
public void test4(){
}
Your perTestSetup() method isn't doing what you think it is doing. The #Before annotation means the test environment will run this method once, before doing any of the tests, rather than once per test. Before I finished reading your question, I was actually itching to advise you to rename this method to simply setup(), as that would be a more accurate description.
Options:
Change the annotation to #BeforeEach, which would then change the behaviour to do what you think it should currently be doing. However, this would be inefficient as in the second two tests you will be defining behaviour and then immediately redefining it.
What do the parameters look like in your functionCall(...)? It may be possible to define two separate behaviours in your single #Before setup() method, i.e.
when(MockClass.functionCall(good values)).thenReturn(mockResult);
when(MockClass.functionCall(bad values)).thenThrow(new RuntimeException());
In each test, call functionCall() with the relevant values for that that particular test.
If the parameters in functionCall() do not readily accommodate the previous approach, consider making two separate instantiations of MockClass, something like
MockClass successfulMockClass = new mock(MockClass.class);
when(successfulMockClass()).thenReturn(mockResult);
MockClass unsuccessfulMockClass = new mock(MockClass.class);
when(unsuccessfulMockClass()).thenThrow(new RuntimeException());
In your tests, call on the relevant mocked object depending on what input you are testing against.
Without being able to see the details of your class, I suspect the second option is what I would go for. It may be worth trying all three to see which feels most intuitive for you, though.

ResourceBundle.getBundle returning actual object in spite of mockStatic and when() directing otherwise

I'm creating tests over existing classes. A number of them have a resource bundle defined as a private final field that's initialized when the object is created via new. I declare a mocked ResourceBundle, use PowerMock's mockStatic method to enable static mocking, and mock the getBundle method to return my mocked ResourceBundle. However, when the constructor runs the code to initialize the field, it simply creates the new resource bundle rather than using the mocked one. I feel like there's one little detail I've missed, but I don't know what it might be.
The reason all this is a problem is this: when I run the test locally, it creates the ResourceBundle object without issue. But when the test is run via our build software (UCBuild), it throws a "can't find resource" exception and the test, and therefore the build, fails.
When I run a test in debug and set a method breakpoint on the constructor, I can see that the "strings" object is created using an actual resource bundle, not the mocked one. I can't for the life of me figure out why.
I've tried declaring the field without initializing it, then using class.getDeclaredField() and Field.setAccesible() to set the resource bundle to point at my mocked one, but of course this just gets overwritten if I run code that re-initializes the field.
The WorkerTest class which tests Worker.java:
#RunWith(PowerMockRunner.class)
#PrepareForTest({FacesContext.class, SaveStatus.class, FacesMessage.class, ResourceBundle.class})
public class WorkerTest {
#Mock
private ResourceBundle mockRB;
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(ResourceBundle.class);
PowerMockito.when(ResourceBundle.getBundle(anyString())).thenReturn(mockRB);
PowerMockito.when(mockRB.getString(anyString())).thenReturn("tst");
sut = new Worker(); // Breakpoint here to verify mockRB exists
}
...some tests
}
Worker.java:
#Named
#ApplicationScoped
public class Worker implements Serializable {
private static final long serialVersionUID = 4075799125164038417L;
private final ResourceBundle strings = ResourceBundle
.getBundle("com.resources.strings");
public Worker() { //method breakpoint here
}
Thanks in advance
Found the problem. Adding Worker.class to the #PrepareForTest annotation line and everything worked fine.

How to mock this callback using Mockito?

I have this production code in my Presenter:
#UiThread
public void tryToReplaceLogo(String emailInitiallySearchedFor, String logoUrl) {
if(isTheEmailWeAskedApiForStillTheSameAsInTheInputField(emailInitiallySearchedFor)){
if (!TextUtils.isEmpty(logoUrl)) {
downloadAndShowImage(logoUrl);
} else {
view.displayDefaultLogo();
}
}
}
public void downloadAndShowImage(String url) {
final Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
view.displayLogoFromBitmap(bitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
Picasso.with(view.getViewContext()).load(url).resize(150, 150).centerInside().into(target);
}
And this unit test for it:
#Test
public void testDisplayLogoIfValidUrlReturnedAndEmailEnteredIsTheSame() throws Exception {
when(loginView.getUserName()).thenReturn(VALID_EMAIL);
when(loginView.getViewContext()).thenReturn(context);
loginLogoFetcherPresenter.onValidateEmailEvent(createSuccessfulValidateEmailEvent(VALID_EMAIL));
waitForAsyncTaskToKickIn();
verify(loginView).displayLogoFromBitmap((Bitmap) anyObject());
}
However, the displayLogoFromBitmap method is never called so my test fails. I need to mock the Target dependency to invoke the onBitmapLoaded method but I don't know how.
Possibly I need to create a static inner class that implements Target so that I can set a Mocked implementation of that in my tests, but how do I invoke the onBitmapLoaded method on the mock?
EDIT:
I have a setter field for Picasso in my LoginPresenter now. In production, (as I am using AndroidAnnotations), I instantiate it in
#AfterInject
void initPicasso() {
picasso = Picasso.with(context):
}
In my test, I mock Picasso like so:
#Mock
Picasso picasso;
#Before
public void setUp() {
picasso = mock(Picasso.class, RETURNS_DEEP_STUBS);
}
(I don't remember why, but I can't use Mockito 2 at this point. It was some incompatibility with something, I think)
In my test case, I got to this point and I don't know what to do:
#Test
public void displayLogoIfValidUrlReturnedAndEmailEnteredIsTheSame() throws Exception {
when(loginView.getUserName()).thenReturn(VALID_EMAIL);
when(loginView.getViewContext()).thenReturn(context);
when(picasso.load(anyString()).resize(anyInt(), anyInt()).centerInside().into(???)) // What do I do here?
loginLogoFetcherPresenter.onValidateEmailEvent(createSuccessfulValidateEmailEvent(VALID_EMAIL));
waitForAsyncTaskToKickIn();
verify(loginView).displayLogoFromBitmap((Bitmap) anyObject());
}
I need to mock the Target dependency
No; do not mock the system under test. Target is as much a part of that system as anything; you wrote the code for it, after all. Remember, once you mock out a class, you commit to not using its implementation, so trying to mock Target to invoke onBitmapLoaded is missing the point.
What's going on here is that you're passing Target—which is real code you wrote that is worth testing—into Picasso, which is external code you didn't write but do depend on. This makes Picasso the dependency worth mocking, with the caveat that mocking interfaces you don't control can get you into trouble if they change (e.g. a method turns final).
So:
Mock your Picasso instance, and the RequestCreator instance Picasso returns when it loads. RequestCreator implements the Builder pattern, so it's a prime candidate for Mockito 2.0's RETURNS_SELF option or other Builder pattern strategies.
Pass the Picasso instance into your system under test, rather than creating it using Picasso.with. At this point you may not need to stub LoginView.getViewContext(), which is a good thing as your test can interact less with hard-to-test Android system classes, and because you've further separated object creation (Picasso) from business logic.
Use an ArgumentCaptor in your test to extract out the Target method that was called on RequestCreator.into.
Test the state of the system before the async callback returns, if you'd like. It's optional, but it's definitely a state your system will be in, and it's easy to forget to test it. You'd probably call verify(view, never()).onBitmapLoaded(any()).
Call target.onBitmapLoaded yourself. You have the target instance at this point, and it should feel correct to explicitly call your code (that is written in your system-under-test) from your test.
Assert your after-callback state, which here would be verify(view).onBitmapLoaded(any()).
Note that there is an existing test helper called MockPicasso, but it seems to require Robolectric, and I haven't reviewed its safety or utility myself.

Mockito gives UnfinishedVerificationException when it seems OK

Mockito appears to be throwing an UnfinishedVerificationException when I think I've done everything correctly. Here's my partial test case:
HttpServletRequest req = mock(HttpServletRequest.class);
when(req.getHeader("Authorization")).thenReturn("foo");
HttpServletResponse res = mock(HttpServletResponse.class);
classUnderTest.doMethod(req, res); // Use the mock
verify(res, never());
verify(req).setAttribute(anyString(), anyObject());
And here's the partial class and method:
class ClassUnderTest extends AnotherClass {
#Override
public String doMethod(ServletRequest req, ServletRequest res) {
// etc.
return "someString";
}
}
Ignoring the fact that you should never mock interfaces you don't own, why is Mockito giving me the following message?
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-> at (redacted)
Example of correct verification:
verify(mock).doSomething()
Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
at [test method name and class redacted]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
... etc
This might also be caused if you try to verify a method which expects primitive arguments with any():
For example, if our method has this signature:
method(long l, String s);
And you try to verify it like this, it will fail with aforementioned message:
verify(service).method(any(), anyString());
Change it to anyLong() and it will work:
verify(service).method(anyLong(), anyString());
I just came across this my self and it caused me a lot of confusion.
As David mentioned above Mockito reports errors in the next Mockito method call which may not be in the same test method. While the exception message does contain a reference to the actual place the error occurred I find having incorrect tests failing counter productive to the testing process. And the simpler the tests the more likely an error is to show up in the next test!
Here is an easy fix that will ensure errors appear in the correct test method:
#After
public void validate() {
validateMockitoUsage();
}
From the Mockito documentation here:
Mockito throws exceptions if you misuse it so that you know if your
tests are written correctly. The gotcha is that Mockito does the
validation next time you use the framework (e.g. next time you verify,
stub, call mock etc.). But even though the exception might be thrown
in the next test, the exception message contains a navigable stack
trace element with location of the defect. Hence you can click and
find the place where Mockito was misused.
Sometimes though, you might
want to validate the framework usage explicitly. For example, one of
the users wanted to put validateMockitoUsage() in his #After method so
that he knows immediately when he misused Mockito. Without it, he
would have known about it not sooner than next time he used the
framework. One more benefit of having validateMockitoUsage() in #After
is that jUnit runner will always fail in the test method with defect
whereas ordinary 'next-time' validation might fail the next test
method. But even though JUnit might report next test as red, don't
worry about it and just click at navigable stack trace element in the
exception message to instantly locate the place where you misused
mockito.
I was getting this same error due to using any() with a boolean parameter, when apparently it needed to be anyBoolean().
In my case, using kotlin was because the funcion to test was not declared as open.
The exception notices that no final/private/equals/hash methods can be used.
fun increment(){
i++
}
to
open fun increment(){
i++
}
With Junit 5, you can add the following to show more meaningful Mockito exceptions in the console
#AfterEach
public void validate() {
validateMockitoUsage()
}
Also see this answer: https://stackoverflow.com/a/22550055/8073652
I had similar exception with class MyRepository
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-> at MyRepository$$FastClassBySpringCGLIB$$de8d8358.invoke()
Example of correct verification:
verify(mock).doSomething()
The problem was resolved when I created interface for MyRepository, and mock interface, but not implementation.
It seems spring creates some CGLIB proxies and it leads to UnfinishedVerificationException exception.
For me the issue turned out to be a missing bean declaration in the test context xml. It was for a custom aspect class used by another class, an instance of which is a parameter to the constructor of the class which is the parameter to failing verify() call. So I added the bean declaration to the context xml and it worked fine after that.
Changed to #RunWith(PowerMockRunner.class) and the issue went away.
Was using #RunWith(MockitoJUnitRunner.class) earlier.
Hope that helps someone..
I had the same issue, too, on the following stack:
Kotlin
Junit 4.13
Mockito 2.28.2 + Mockito-Inline 2.13.0
Robolectric 4.3.1
I tried to verify a lambda call:
#RunWith(RobolectricTestRunner::class)
class MainViewTest {
#get:Rule
val mockitoRule: MockitoRule = MockitoJUnit.rule()
#Mock private lateinit var mockClickCallback: () -> Unit
#Test
fun `should call clickCallback on the button click`() {
val activity = Robolectric.buildActivity(MainActivity::class.java).create().get()
val viewUnderTest = MainView(activity)
viewUnderTest.setClickCallback(mockClickCallback)
viewUnderTest.button.performClick()
verify(mockClickCallback).invoke() // UnfinishedVerificationException
}
}
Then I found the issue on Github, it seems that the problem is in Robolectric. I used the following workaround:
#RunWith(RobolectricTestRunner::class)
class MainViewTest {
private interface UnitFunction: () -> Unit
#Test
fun `should call clickCallback on the button click`() {
val activity = Robolectric.buildActivity(MainActivity::class.java).create().get()
val viewUnderTest = MainView(activity)
val mockClickCallback = mock(UnitFunction::class.java) as () -> Unit
viewUnderTest.setClickCallback(mockClickCallback)
viewUnderTest.button.performClick()
verify(mockClickCallback).invoke() // OK
}
}
Two answers above suggested using validateMockitoUsage() method after each test.
While this is correct I found that annotating your class with #ExtendWith(MockitoExtension.class)
in Junit 5 give the same effect while adding some the nice Mockito functionalities. Also, it looks cleaner to me as well.
I guess Junit 4 #RunWith(MockitoJUnitRunner.class) will give a similar result but I didn't test it.
I had a similar problem, i found a way to solve this. Mock objects which you for verify haven't been reseted, so you should reset it .You can reset(mock) before your test case function, it may be helpful.
If you try to verify a private or package-private method with Mockito.verify you will get this error.
If you don't want to use PowerMockito you can set your method as protected and I advise you to add the #VisibleForTesting tag:
Before:
void doSomething() {
//Some behaviour
}
After :
#VisibleForTesting
protected void doSomething() {
//Some behaviour
}
I was having the same error
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-at com.xxx.MyTest.testRun_Should_xxx_When_yyy(MyTest.java:127)
Example of correct verification:
verify(mock).doSomething()
Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
at com.xxx.MyTest.validate(MyTest.java:132)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.internal.runners.MethodRoadie.runAfters(MethodRoadie.java:145)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:99)
...
In my case, the error was generated because I was using a PowerMockito.verifyStatic() before my Mockito.verify(...) call, then I had to move the PowerMockito.verifyStatic() to last line (or delete it).
From:
PowerMockito.verifyStatic();
Mockito.verify(myMock, Mockito.times(1)).myMockedMethod(anyString(), anyString(), anyString(), any(XXX.class), any(YYY.class), any(ZZZ.class));
To:
Mockito.verify(myMock, Mockito.times(1)).myMockedMethod(anyString(), anyString(), anyString(), any(XXX.class), any(YYY.class), any(ZZZ.class));
PowerMockito.verifyStatic();
Here is my grain of salt!
I discovered there is a conflict between Mockito and Hibernate Validation.
My solution is the separate my contract checks (#NotNull, #NotEmpty, etc) from the mockito tests. I also started using validateMockitoUsage() to ensure everything was run correctly.
The tests run individually well but while running integration test suite it fails with the UnfinishedVerificationException. The issue arises when we use verify() from mockito and have #EnableRetry.
Workaround for this is to use
public static <T> T unwrapAndVerify(T mock, VerificationMode mode) {
return ((T) Mockito.verify(AopTestUtils.getTargetObject(mock), mode));
}
as mentioned in Mocked Spring #Service that has #Retryable annotations on methods fails with UnfinishedVerificationException
I'm not sure where are your "classUnderTest" come from, but please keep sure it's mocked, not a real one.
I have the same issue for my test case below:
MyAgent rpc = new MyAgent("myNodeName");
...
rpc.doSomething();
...
PowerMockito.verifyPrivate(rpc).invoke("initPowerSwitch");
PowerMockito.verifyPrivate(rpc).invoke("init", "192.168.0.23", "b2", 3);
But it's disappeared for the following test case:
MyAgent rpc = PowerMockito.spy(new MyAgent("myNodeName"));
...
rpc.doSomething();
...
PowerMockito.verifyPrivate(rpc).invoke("initPowerSwitch");
PowerMockito.verifyPrivate(rpc).invoke("init", "192.168.0.23", "b2", 3);
Attention, the Object rpc should be mocked by PowerMockito.spy(...).
Faced same exception when used mockStatic method and called Mockito.verify multiple times, but passed interface instead of implementing class.
wrong code:
try (MockedStatic<Service> staticMock = Mockito.mockStatic(Service.class, Mockito.CALLS_REAL_METHODS)) {
staticMock.verify(() -> ServiceImpl.method()); // passed without errors
staticMock.verify(() -> ServiceImpl.method()); // throws UnfinishedVerificationException
}
fixed code:
try (MockedStatic<ServiceImpl> staticMock = Mockito.mockStatic(Service.class, Mockito.CALLS_REAL_METHODS)) {
staticMock.verify(() -> ServiceImpl.method());
staticMock.verify(() -> ServiceImpl.method());
}
It was my mistake obviosly, but UnfinishedVerificationException message was not helpfull