QuarkusTest with Mongo and PanacheMock in Kotlin failing on Mokito.when - unit-testing

I am working on a Quarkus project with MongoDB and Kotlin using PanacheMongoEntity.
The Problem:
Mockito.when throws an error when using with PanacheMock.mock
The error:
when() requires an argument which has to be 'a method call on a mock'.
See the error logs (at bottom) for more info.
Question:
Is it even possible to do it this way in Quarkus-Kotlin?
The documentation at https://quarkus.io/guides/mongodb-panache-kotlin does not cover the testing part, it just refers to the java examples.
Code examples
Dependencies (Gradle)
dependencies {
implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
implementation 'io.quarkus:quarkus-arc'
implementation 'io.quarkus:quarkus-kotlin'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'io.quarkus:quarkus-resteasy-jackson'
implementation 'io.quarkus:quarkus-mongodb-panache-kotlin'
implementation 'io.quarkus:quarkus-security-jpa'
// TESTING
testImplementation 'io.quarkus:quarkus-junit5'
testImplementation 'io.rest-assured:rest-assured'
testImplementation 'io.quarkus:quarkus-panache-mock'
// makes final classes testable remove when mockito core implemented
testImplementation 'org.mockito:mockito-inline'
testImplementation 'io.rest-assured:kotlin-extensions'
}
The entity
#MongoEntity(collection = "anything")
class Anything : PanacheMongoEntity() {
companion object : PanacheMongoCompanion<Anything> {}
lateinit var id: String
lateinit var type: String
}
The test:
#QuarkusTest
class AnythingResourceTest {
#Test
fun testFetchAllAnythings() {
PanacheMock.mock(Anything::class.java)
val anything = Anything()
anything.id = "id"
anything.type = "type"
Mockito.`when`(Anything.Companion.listAll()).thenReturn(listOf(anything))
}
}
The resulting error log
2022-08-23 19:03:11,290 INFO [org.mon.dri.connection] (Test worker) Opened connection [connectionId{localValue:3, serverValue:137}] to localhost:27017
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
at com.asking.AnythingResourceTest.testFetchAllAnythings(AnythingResourceTest.kt:12)
at java.base#17.0.2/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base#17.0.2/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base#17.0.2/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base#17.0.2/java.lang.reflect.Method.invoke(Method.java:568)

Related

How to use #MockBean without having to #Inject the Bean again?

Is there a more concise / elegant way to reach this functionality in Micronaut?
#MicronautTest
class ControllerTest {
#Inject
#field:Client("/")
lateinit var client: RxHttpClient
#Inject
lateinit var redeemService: RedeemService
#MockBean(RedeemService::class)
fun redeemService(): RedeemService = mockk {
every { validate(any()) } returns true
}
#Test
fun test() {
// some logic triggering a call to redeemService
verify(exactly = 1) {
redeemService.validate("123")
}
}
}
To me it looks like redundant work to have to declare the #MockBean and then also having to #Inject the previously declared #MockBean.
From what I remember, in Spring Boot this is just an annotation on a lateinit var.
Did I misunderstand or overlook something?
You need the mock bean, for replacing the service and inject it everywhere in your application .. if you want to do some verification you eighter have to inject it back or create instance within your class and return that with the mock bean
private val redeemService: RedeemService = mockk {
every { validate(any()) } returns true
}
#MockBean(RedeemService::class)
fun redeemService() = redeemService
Usually, MockBean are NO-OP collaborators that are intended to be DI-ed into dependent beans instead of relying on concrete bean implementations.
If within a test fixture ~ your tested feature scope ~ you have to verify collaborator calls or provide custom response to other collaborators calls, then you have to inject it.
This may seem, as stated, like redundancy but it's not and it SHOULD be done in such a way otherwise Micronaut (or any other framework doing so) would have a little design flaw.
Relying on custom implementations (annotations in this case) to act as bean providers and injection points within tests would result in non-deterministic behavior and internal tight-coupling to framework specificities as you will be injecting your dependencies in your test fixture differently from the way you'll be doing it in your actual application code, and that should be avoided.
In short, if your bean (mock or concrete) make it to the your test implementation through the #Inject annotation, then you are assured it will work the same when injected into real application code since a test fixture is a bean itself.

spy on mocked object accessor (get and set)

Mocking out dependencies while testing angular components. ComponentA injects ServiceA, I want to mock serviceA in my test
class ServiceA {
private _prop = 1;
get prop (): number {
return this._prop;
}
set prop(p: number) {
this._prop;
}
}
class ComponentA {
private injectedService: ServiceA;
constructor(private injectedService: ServiceA) {
this.injectedService = injectedService;
}
method () {
this.injectedService.prop = this.injectedService.prop + 1;
if (this.injectedService.prop === 5) {
this.injectedService.prop = 1;
}
}
}
With the above program structure it is important to have a serviceA mock that has accessor(getter and setter for injectedService.prop) implementation, since a part of the program is dependent on the value of injectedService.prop that was prior set.
Options that I have tried:
ts-mockito: ts-mockito mocks does not have access type set. With this limitation ts setter won't be recognised. A workaround would be to define actual methods to 'set' and 'get' and call these methods. setter would still need a more workaround as below:
// default get stub
when(mock.getProp()).thenReturn();
// setter redefines get stub
when(mock.setProp(anything())).thenCall((p) => {
when(mock.getProp()).thenReturn(a);
});
typemoq:
static mock calls constructor, big flaw when target mock class as other dependency injection(s)
dynamic mock conditions like (this.injectedService.prop === 5) will never be truthy beacuse this.injectedService.prop (i.e mock.object.prop) points to a function. On this I feel there could be a way that I'm yet to figure out, I would appreciate any help
(Personal preference) I prefer jasmine spyOn to typemoq verify for assertions on my mocks. This could be ignored if not possible.
Things I don't want to do
I do not want to modify classes to be mocked except to add standard typescript accessors
I do not want to create an Interface/Class off classes to be mocked just for the purpose of creating a mock for test
Although I'm open to compromise on above if there is a good justification or standard
I would also appreciate if anybody could direct me to code base(s) that has proper test and follows standard if any.
Note: I'm testing an angular app with karma + jasmine ... but all these doesn't count as I am merely creating class from constructor, no Testbed just simple typescript class unit-test.

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

GWTP unit testing using Mockito

I am trying to use Mockito to test my GWTP application.
I am trying to Mock my View,Proxy,Placemanager and eventbus.
I tried using
#Mock
AbcView abc;
and Abcview abc = Mockito.mock(AbcView.class);
However every time the mocked view is instantiated as null.
How shall i address the same?
Once the view is mocked i will be able go on with testing my presenter class, as the constructor of presenter has following code:
getView().setUiHandlers( this );
so until view is instantiated properly null pointer exception is thrown.
Did you run your test using the MockitoJUnitRunner runner?
#RunWith(MockitoJUnitRunner.class)
public class ExampleTest {
#Mock
private List list;
#Test
public void shouldDoSomething() {
list.add(100);
}
}
Besides #Sydney's response, you also need o make sure that AbcView.class is not final. I forget whether a final class results in a null or a runtime error, but that can be a cause for some sort of unexpected behavior -- one way or another, the mocking doesn't work. And if the class is not final, you need to make sure that any methods you stub on that mock are not final.

How to cleanly unit test a custom ValueResolver ResolveCore(...) method

I'm trying to unit test a custom ValueResolver (Automapper) but am running into problems because the method it forces me to override is not exposed directly in the custom object we must create. I override the protected method "ResolveCore" but the only public method exposed is "Resolve" which expects a complex "ResolutionResult" automapper object as it's input. In the vein of true unit testing I want to test this object / method in isolation to anything else and don't really want to go the route of firing up automapper with mappings to do this test. Likewise it's not possible to Mock "ResolutionResult" and it seems a very complex object to setup for each test (again requiring creation / association of other Automapper objects).
The only (less than ideal) solution I can come up with (and have seen suggested when Googling for a solution) is to stub a public method inside the class that exposes the protected overriden method. If we must go down this route then so be it, but has anyone else got a better solution that tests the method call in isolation doesn't require a modification of the object we are trying to test?
Example code:
public class CustomResolver : ValueResolver<Supplier, string>
{
protected override string ResolveCore(Custom source)
{
return string.Format("{0} {1}", source.Name, source.Descripton);
}
public string UnitTestStub(Custom source)
{
return ResolveCore(source);
}
}
I wouldn't place a public stub in your class. Instead, I'd just create a simple subclass in my unit test assembly that exposes the call I wanted to test:
public class TestCustomResolver : CustomResolver
{
public string TestResolveCore(Custom source)
{
return this.ResolveCore(source);
}
}
Some of this depends on the unit testing framework you're using too. For example, you could use the InternalsVisibleTo() attribute to expose your internals to your unit tests. However, I would lean towards a simple subclass in your unit tests.