How to migrate PowerMockito whenNew thenThrow to Mockito Inline MockedConstruction - java

We're migrating all our code away from PowerMock to Mockito Inline, I've mostly been able to migrate all cases but I don't know how throw an exception when an instance of a specific class is created, using Mockito MockedConstruction.
i.e I need to migrate to Mockito Inline from this:
whenNew(MyClass.class).withAnyArguments().thenThrow(new MyException("fail"));
I've read the docs and I can't find how to do it.
I've tried this:
try (MockedConstruction<MyClass> ignored = mockConstruction(MyClass.class,
(mock, context) -> { when(new MyClass(any())).thenThrow(new MyException("fail"));})
) {
stuffToTest();
}
I've also tried the suggested solution here but it doesn't work.

Related

Replace PowerMockito.verifyStatic by Mockito.verify on Android

Mockito seems to get more and more of PowerMockito's features.
When I updated to
junitVersion = "4.13.2"
mockitoVersion = "4.2.0"
hamcrestVersion = "2.2"
powermockVersion = "2.0.9"
tests are failing.
So I am trying to get rid of PowerMokito.
Problem is there is no verifyStatic
https://www.javadoc.io/doc/org.powermock/powermock-api-mockito/latest/org/powermock/api/mockito/PowerMockito.html#verifyStatic-java.lang.Class-org.mockito.verification.VerificationMode-
https://github.com/telekom/SmartCredentials-SDK-android/blob/develop/SmartCredentials_aOS/camera/src/test/java/de/telekom/smartcredentials/camera/views/presenters/CameraViewPresenterTest.java#L66
How do I replace
PowerMockito.verifyStatic(ApiLoggerResolver.class);
Do I just write
Mockito.verify(ApiLoggerResolver.class);
or do I have to do a
MockedStatic<ApiLoggerResolver> apiLoggerResolverMockedStatic = Mockito.mockStatic(ApiLoggerResolver.class);
Mockito.verify(apiLoggerResolverMockedStatic);
This does not work on Android which I need and what triggered this question.
Mockito's inline mock maker supports static mocks based on the Instrumentation API.
You can simply enable this mock mode, by placing the 'mockito-inline' artifact where you are currently using 'mockito-core'.
Note that Mockito's inline mock maker is not supported on Android.
I am using mockito-core but it seems that mockito-inline does not work on Android. Maybe the next version is going to support Android?!

Can I mock Kotlin service into java Junit test

I'm currently writing Junit test with Mockito in java. But one microservice is written in Kotlin.
I try to mock the kotlin service, but it doesn't work as I excepted.
I plan to return a customize response inside the test, I checked it with debugger, instead of returning the response, it always runs into the kotlin function(getFile).
#Mock
private FileService fileservice; // this service written in Kotlin
#Before
public void setUp() {
Response respone = new Response(...);
when(fileservice.getFile(any())).thenReturn(response);
}
The best approach is to use mocking library designed for Kotlin, there is few options for this:
If still needed to stick to mockito, there is official mockito support for kotlin, more details here: https://github.com/mockito/mockito-kotlin
Also there is mockk library that specially designed for kotlin, and it better fits than mockito: https://mockk.io/
Also many java libraries using byte-code generated proxies like mockito does, while kotlin makes every class final by default, there is a kotlin plugin named all-open, which can make all needed classes open: https://kotlinlang.org/docs/all-open-plugin.html

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.

JUnit without inversion of control

Currently the JUnit5 Framework works with Inversion of Control. I.e. you annotate a test method with #Test and then JUnit scans your classpath (in the simplest case)
Now is there a way for me to be in charge of calling the test cases through JUnit APIs? Maybe by hooking my test implementations to some test registry provided by JUnit?
I'm pretty new to JUnit - how did older versions go about this?
The reason I'm asking is that normally to execute my test cases, I'd have to run something along the lines of
java -jar junit-platform-standalone.jar --class-path target --scan-class-path
on the command line. My situation requires me to run the test cases through by executing one of my own classes, like that e.g.
java /com/example/MyTestCassesLauncher
EDIT: to clarify, I need one of my own classes to be hosting/launching my test cases, something like this:
// Maybe this needs to extend one of JUnit's launchers?
public class MyTestCassesLauncher {
public static void main(String[] args) {
JUnitLauncher.launchTests(new MyTestClass());
}
}
where JUnitLauncher.launchTests is some kind of API provided by the platform. I'm not looking for a method with that exact same signature but a mechanism that would allow me to ultimately call my own MyTestClassesLauncher class to run the tests.
Thanks in advance.
Not sure what you arÄ™ actually trying to achieve but in Junit5 to change behaviour of your tests you can use Extensions mechanism, similar to Junit4 RunWith but more powerful
Such custom extension can provide some additional logic like in this logging example
public class LoggingExtension implements
TestInstancePostProcessor {
#Override
public void postProcessTestInstance(Object testInstance,
ExtensionContext context) throws Exception {
Logger logger = LogManager.getLogger(testInstance.getClass());
testInstance.getClass()
.getMethod("setLogger", Logger.class)
.invoke(testInstance, logger);
}
}
The way Junit controls it's flow is Junit problem - you should not modify framework but extend it

JUnit 5, pass information from test class to extension

I am trying to write an extension for Junit5 similar to what I had for Junit4 but I am failing to grasp how to do that in the new (stateless) extension system.
The idea in the previous version was that user could pass information into extension class and hence change the way it behaved. Here is a pseudo snippet showing approximately what is used to do:
public void MyTest {
// here I can define different behaviour for my extension
#Rule MyCustomRule rule = MyCustomRule.of(Foo.class).withPackage(Bar.class.getPackage).alsoUse(Cookies.class);
#Test
public void someTest() {
// some test code already affected by the #Rule
// plus, user has access to that class and can use it, say, retrieve additional information
rule.grabInfoAboutStuff();
}
}
Now, I know how to operate JUnit 5 extension, what lifecycles to use etc. But I don't know how to give the test-writer the power to modify my extension's behaviour with JUnit5. Any pointers appreciated.
As of JUnit Jupiter 5.0.1, it is unfortunately not possible to pass parameters to an Extension programmatically like you could for rules in JUnit 4.
However, I am working on adding such support in JUnit Jupiter 5.1. You can follow the following issue if you like: https://github.com/junit-team/junit5/issues/497
In the interim, the only way to pass information to an extension is for the extension to support custom annotations and extract the user-supplied information from there. For example, I allow users to provide a custom SpEL expression in the #EnabledIf annotation in the Spring Framework, and my ExecutionCondition extension pulls the expression from the annotation using reflection.
followup on the (accepted) answer from Sam as in the meantime the referred bug has been implemented with junit 5.1
use #RegisterExtension
see https://junit.org/junit5/docs/current/user-guide/#extensions-registration-programmatic

Categories

Resources