I am trying to use Reflections in my Java project (also using Spring boot), and I have to get all the classes of a package that implements an interface.
public static Object[] getClasses(String packageName) throws IOException
{
Reflections r = new Reflections(packageName);
Set<Class<? extends EntityXML>> allClasses = r.getSubTypesOf(EntityXML.class);
return (Object[]) allClasses.toArray();
}
But it returns me always this error.
java.lang.NoSuchMethodError: com.google.common.collect.Sets$SetView.iterator()Lcom/google/common/collect/UnmodifiableIterator;
at org.reflections.Reflections.expandSuperTypes(Reflections.java:380)
at org.reflections.Reflections.<init>(Reflections.java:126)
at org.reflections.Reflections.<init>(Reflections.java:168)
at org.reflections.Reflections.<init>(Reflections.java:141)
at gcs.fds.focus.lib.utils.FindPackages.getClasses(FindPackages.java:14)
...
I try to import the google.guava package to avoid this error, and it fix it, but I would like not to import it, because it is a package without use in my project.
Any idea about how to avoid this error?
Okey I solved!
I deleted the google.guava dependency, and I make a
mvn dependency:tree
where I could see that other of my dependencies imports also google.guava, but version 19 which I read that makes this conflict. (everit.json dependency), so I exclude the google.guava from this dependency and it works!
<dependency>
<groupId>org.everit.json</groupId>
<artifactId>org.everit.json.schema</artifactId>
<version>1.3.0</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
Related
I have project in java and i am using Allure for generating a test report.
I found this question and I need to rename my test using the below code:
AllureLifecycle lifecycle = Allure.getLifecycle();
//change test name to "CHANGED_NAME"
lifecycle.updateTestCase(testResult -> testResult.setName("CHANGED_NAME"));
I have imported the AllureLifecycle from below:
import io.qameta.allure.AllureLifecycle;
and using the below dependency:
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-java-commons</artifactId>
<version>2.13.3</version>
</dependency>
But, in the line Allure.getLifecycle() it is complaining with Cannot resolve method 'getLifecycle' in 'Allure'.
How can fix the error?
You need to add import of io.qameta.allure.Allure class
I'm using Spring Boot and in one of my unit test, I need to mock the Files.delete(somePath) function. Which is a static void method.
I know that with Mockito it is possible to mock void method:
doNothing().when(MyClass.class).myVoidMethod()
And since July 10th 2020, it is possible to mock static method:
try (MockedStatic<MyStaticClass> mockedStaticClass = Mockito.mockStatic(MyStaticClass.class)) {
mockedStaticClass.when(MyStaticClass::giveMeANumber).thenReturn(1L);
assertThat(MyStaticClass.giveMeANumber()).isEqualTo(1L);
}
But I can't manage to mock a static void mehtod such as Files.delete(somePath).
This is my pom.xml file (only test related dependencies):
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.5.15</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.5.15</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.5.15</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
Is there a way to mock static void methods without using PowerMockito ?
If it is possible, what is the correct syntax to do so ?
In general mocking static calls is the last resort, that is not supposed to be used as default approach.
For example, for testing the code, that works with file system, there are better means. E.g. depending on the junit version either use TemporaryFolder rule or #TempDir annotation.
Also, please note, that Mockito.mockStatic might significantly slow down your tests (e.g. look at the notes below).
Having said the caution above, find the snippet below, that shows how to test, that file got removed.
class FileRemover {
public static void deleteFile(Path filePath) throws IOException {
Files.delete(filePath);
}
}
class FileRemoverTest {
#TempDir
Path directory;
#Test
void fileIsRemovedWithTemporaryDirectory() throws IOException {
Path fileToDelete = directory.resolve("fileToDelete");
Files.createFile(fileToDelete);
FileRemover.deleteFile(fileToDelete);
assertFalse(Files.exists(fileToDelete));
}
#Test
void fileIsRemovedWithMockStatic() throws IOException {
Path fileToDelete = Paths.get("fileToDelete");
try (MockedStatic<Files> removerMock = Mockito.mockStatic(Files.class)) {
removerMock.when(() -> Files.delete(fileToDelete)).thenAnswer((Answer<Void>) invocation -> null);
// alternatively
// removerMock.when(() -> Files.delete(fileToDelete)).thenAnswer(Answers.RETURNS_DEFAULTS);
FileRemover.deleteFile(fileToDelete);
removerMock.verify(() -> Files.delete(fileToDelete));
}
}
}
Notes:
Mockito.mockStatic is available in Mockito 3.4 and above, so check you're using correct version.
The snippet deliberatly shows two approaches: #TempDir and Mockito.mockStatic. When run both tests you'll notice that Mockito.mockStatic is much slower. E.g. on my system test with Mockito.mockStatic runs around 900 msec vs 10 msec for #TempDir.
Can I have a sample routine (that has been tested) on latest T24/Transact release using Temenos Java APIs?
As per Temenos, Infobasic routines cannot be used anymore if EXTENSIBLE.CUSTOMISATION flag is set to Y in SPF.
Here is an actual, working sample that works in R20 - it is a sample of ENQUIRY build routine:
package com.bank;
import java.util.List;
import com.temenos.api.TStructure;
import com.temenos.t24.api.complex.eb.enquiryhook.FilterCriteria;
import com.temenos.t24.api.complex.eb.enquiryhook.EnquiryContext;
import com.temenos.t24.api.hook.system.Enquiry;
public class EnqBuildRoutineTest extends Enquiry {
#Override
public List<FilterCriteria> setFilterCriteria(List<FilterCriteria> filterCriteria, EnquiryContext enquiryContext) {
FilterCriteria criteria = new FilterCriteria();
criteria.setFieldname("SECTOR.CODE");
criteria.setOperand("LK");
criteria.setValue("2...");
filterCriteria.add(criteria);
return filterCriteria;
}
}
In case you are using maven, you can use these dependencies in pom.xml:
<dependency>
<groupId>com.temenos</groupId>
<artifactId>api</artifactId>
<scope>system</scope>
<systemPath>c:/Temenos/R20_MB/TAFJ/lib/TAFJClient.jar</systemPath>
<version>1</version>
</dependency>
<dependency>
<groupId>com.temenos</groupId>
<artifactId>EnquiryHook</artifactId>
<scope>system</scope>
<systemPath>c:/Temenos/R20_MB/bnk/t24lib/EB_EnquiryHook.jar</systemPath>
<version>1</version>
</dependency>
Once you have packaged it inside JAR and placed in your Classpath, you need to create EB.API record with "Source Type = Method" and specify the overriden setFilterCriteria as the method inside EB.API record. You also need to specify Class name (EnqBuildRoutineTest in this case) and package name (com.bank).
I have a java application (no Spring inside) that I want to test with an integration test.
My main use case is the main function that with a specified input do some things on the database and send some request to two different services, one SOAP and one REST.
Now I have a working JUnit configuration (splitted in unit and integration tests) + io.fabric8:docker-maven-plugin that use a docker image for the database during integration tests.
What I'm trying to do is to add a mock for these 2 services, in particular, the method that is used to call directly the external service.
The big problem is that I have this structure:
class A{
Result mainFunction(Request r){
....
B b = new B(params);
b.logEvent(someParameters)
....
}
}
class B{
int logEvent(Object someParameters){
....
NotifierHandler nh = new NotifierHandler(param1);
nh.sendNotification(json);
....
}
}
where I have:
class NotifierHandler{
String sendNotification(Json j){
...
[call to REST service with some parameters]
...
...
[call to SOAP service with some parameters]
...
}
}
What I need: call A.mainFunction(r) having, in the test environment, replaced the NotifierHandler with a FakeNotifierHandler and/or change the behaviour of the method sendNotification().
Actual problems: Using Mockito and PowerMock now I have the problem that I'm not able to change globally and directly the class NotifierHandler with FakeNotifierHandler. The same trying to changing the behaviour of the method.
In particular, what I need is to create a
class FakeNotifierHandler{
String sendNotification(Json j){
...
[save on an HashMap what I should send to the REST service]
...
...
[save on another HashMap what I should send to the SOAP service]
...
}
}
Reading all example that I tryed I saw only simple examples that change the return value of a method and not the behaviour of one method of one class used by another and another that I'm using as the start point of the integration test.
NOTE: probably there is a fast way to do this but I'm very new on this type of tests (Mockito, PowerMock,...) and I have found no example for this particular strange case.
EDIT: not similar to How to mock constructor with PowerMockito because I need to change the behaviour of the method, not only the return value.
Thanks a lot in advance
I found a solution that works very well and it is very simple!
The solution is PowerMock (https://github.com/powermock/powermock) and in particular replace the creation of an instance of a class with another: https://github.com/powermock/powermock/wiki/mockito#how-to-mock-construction-of-new-objects
There is only one problem in my project and it is JUnit 5. PowerMock support JUnit 4 and for this reason, only for some tests of the solution are using it.
In order to do this there is the needed to replace
import org.junit.jupiter.api.Test;
with
import org.junit.Test;
In order to use teh "whenNew()" methods I had extented the class that in tests must be replaced and I have overwritten only methods that are necessary for the integration test.
The big benefit of this solution is that my code is untouched and I can use this approach also on old code without the risk of introducing regressions during the refactor of the code.
Regarding the code of a integration test, here an example:
import org.junit.jupiter.api.DisplayName;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PowerMockIgnore({"javax.crypto.*" }) // https://github.com/powermock/powermock/issues/294
#PrepareForTest(LegacyCoreNetworkClassPlg.class) // it is the class that contains the "new SOAPCallHelper(..)" code that I want to intercept and replace with a stub
public class ITestExample extends InitTestSuite {
#Test
#DisplayName("Test the update of a document status")
public void iTestStubLegacyNetworkCall() throws Exception {
// I'm using JUnit 4
// I need to call #BeforeAll defined in InitTestSuite.init();
// that works only with JUnit 5
init();
LOG.debug("IN stubbing...");
SOAPCallHelperStub stub = new SOAPCallHelperStub("empty");
PowerMockito.whenNew(SOAPCallHelper.class).withAnyArguments().thenReturn(stub);
LOG.debug("OUT stubbing!!!");
LOG.debug("IN iTestStubLegacyNetworkCall");
...
// Here I can create any instance of every class, but when an instance of
// LegacyCoreNetworkClassPlg.class is created directly or indirectly, PowerMock
// is checking it and when LegacyCoreNetworkClassPlg.class will create a new
// instance of SOAPCallHelper it will change it with the
// SOAPCallHelperStub instance.
...
LOG.debug("OUT iTestStubLegacyNetworkCall");
}
}
Here the configuration of the pom.xml
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.jupiter.version>5.5.2</junit.jupiter.version>
<junit.vintage.version>5.5.2</junit.vintage.version>
<junit.platform.version>1.3.2</junit.platform.version>
<junit.platform.engine.version>1.5.2</junit.platform.engine.version>
<powermock.version>2.0.2</powermock.version>
<!-- FOR TEST -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- Only required to run tests in an IDE that bundles an older version -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<!-- Only required to run tests in an IDE that bundles an older version -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<!-- Only required to run tests in an IDE that bundles an older version -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.vintage.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>${junit.platform.engine.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.vintage.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
I think the main headache in your case is that you have tightly coupled dependencies between class A, B and NotifierHandler. I would start with:
class A {
private B b;
public A(B b) {
this.b = b;
}
Result mainFunction(Request r){
....
b.logEvent(someParameters)
....
}
}
class B {
private NotifierHandler nh;
public B(NotifierHandler nh) {
this.nh = nh;
}
int logEvent(Object someParameters){
....
nh.sendNotification(json);
....
}
}
Make NotifierHanlder an interface:
interface NotifierHandler {
String sendNotification(String json);
}
and make two implementations: one for a real use case, and one fake that you can stub whatever you want:
class FakeNotifierHandler implements NotifierHandler {
#Override
public String sendNotification(String json) {
// whatever is needed for you
}
}
Inject FakeNotifierHandler in your test.
I hope this helps you.
I'm trying to use Reflections classes as suggested here
stackoverflow.com/questions/12538761/
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeType>> subTypes =
reflections.getSubTypesOf(SomeType.class);
Set<SomeType> someTypes = new HashSet<SomeType>(subTypes.size());
for (Class<? extends SubType> subType : subTypes) {
someTypes.add(subType.newInstance());
}
However, I cant seem to import the necessary package. NetBeans cant find it, and also I tried importing java.lang.reflections but it doesn't do it.
I can see java.lang.Class, but I don't see Reflections class anywhere.
Reflections isn't part of Java, it's a 3rd party library. First, you need to add the relevant Jar to your classpath. E.g., if you're using Maven, you could add the following dependency:
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
Once you've done that, you need to import the Reflections class, as you noted. It is located in the org.reflections package:
import org.reflections.Reflections
It's a library https://github.com/ronmamo/reflections
Add it via Maven, Gradle or manually