Replace PowerMockito.verifyStatic by Mockito.verify on Android - java

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?!

Related

How to migrate PowerMockito whenNew thenThrow to Mockito Inline MockedConstruction

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.

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

Is there any way in JUnit > 5.6.0 to load context before class execution condition evaluation?

My goal is to execute tests in test class only when some spring property declared in application-foo.properties is equal to some constant.
I've tried to reach this by writing my own ExecutionCondition with annotation using it, and when I use it on #Test method it works fine. But using one on a test class leads to the problem: condition evaluates before Spring's context is up.
According to the docs:
If an ExecutionCondition disables a test method, that does not prevent
the test class from being instantiated.
But what should I do if I want to?
Script-based condition APIs and their supporting implementations are
deprecated with the intent to remove them in JUnit Jupiter 5.6. Users
should instead rely on a combination of other built-in conditions or
create and use a custom implementation of ExecutionCondition to
evaluate the same conditions.
Since v5.6.0 the #EnabledIf annotation was excluded. One of advantages of this one is loadContext() property, which allows to reach the goal of this topic, literally.
None of remaining annotations (e.g. EnabledIfEnvironmentVariable) contain even a tiny hint, how to reach it. And I haven't found any possibilities in the User Guide as well.
I'll appreciate any help or advice.
Indeed #EnabledIf from import org.junit.jupiter.api.condition.EnabledIf was removed in JUnit 5.6.
There is also #EnabledIf from Spring Test import org.springframework.test.context.junit.jupiter.EnabledIf which is not deprecated and fits your use case.
#EnabledIf(
expression = "#{systemProperties['your.property'].toLowerCase().contains('disabled')}",
reason = "Disabled due to property",
loadContext = true
)
#SpringBootTest
public class MyTest {
// your tests
}
Let's say you have a property inside application-foo.properties:
flaky.tests.enabled = false
You can now conditionally run the tests with
#EnabledIf(
expression = "${flaky.tests.enabled}",
reason = "Disabled flaky tests",
loadContext = true
)
#SpringBootTest
#ActiveProfiles("foo")
public class FlakyTest {
// your tests
}
I tested it with Spring Boot 2.3.0 and it works fine without any deprecation warning.

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

How can I write meaningful unit tests around the Braintree Java API?

I am writing a payment gateway based upon the Java API for Braintree Payments (version 2.71.0 as of writing).
I would like to write unit tests to check that the requests I send to Braintree have the right parameters set. However, it seems that the objects exposed by the Java API are write-only.
Note that I don't want my automated tests to depend upon the availability of the Braintree sandbox: I want to write robust unit tests, not flaky system tests.
In a perfect world, I would like to be able to write something like this (using Mockito and AssertJ):
BraintreeGateway mockGateway = Mockito.mock(BraintreeGateway.class);
TransactionGateway transactionGateway = Mockito.mock(TransactionGateway.class);
Result<Transaction> mockResult = (Result<Transaction>) Mockito.mock(Result.class);
BigDecimal totalAmount = BigDecimal.valueOf(1234, 2);
String customerId = "some-customer-id";
Mockito.when(mockGateway.transaction()).thenReturn(transactionGateway);
Mockito.when(transactionGateway.sale(any())).thenReturn(mockResult);
underTest.performTransaction(totalAmount, customerId);
ArgumentCaptor<TransactionRequest> reqCaptor = ArgumentCaptor.forClass(TransactionRequest.class);
Mockito.verify(transactionGateway).sale(reqCaptor.capture());
TransactionRequest sentRequest = reqCaptor.getValue();
Assertions.assertThat(sentRequest.getAmount()).isEqualTo(totalAmount);
Assertions.assertThat(sentRequest.getCustomer().getId()).isEqualTo(customerId);
Alas, the only methods I get on the sentRequest are setters.
As a workaround, I could try to mock one level deeper and catch the HTTP requests sent by the Braintree API, but that would be hardly readable and (once again) quite flaky.
Any better idea?
I'd wrap the Braintree API into a seperate interfaces and write an integration test for the API, to test the expected behavior. That way you have an integration test to run, when the backend changes (in terms of API, technology and version), you can run smoke tests after a deployment and you can mock the new interface away in your unit test. You shouldn't - actually you can't by definition - unit test a third party system.
What does your test actually test anyway (what's underTest)? It looks it only tests your mocking and argument capturing.
... And if something is hardly readable, it's usually the writers fault :P

Categories

Resources