IDEA, Hamcrest and static imports - java

My maven project includes
186 <dependency>
187 <groupId>org.hamcrest</groupId>
188 <artifactId>hamcrest-all</artifactId>
189 <version>1.3</version>
190 </dependency>
When i type assertThat ..
I'd like for IDEA to figure out that the following is needed
import static org.hamcrest.MatcherAssert.assertThat;
Instead i get this.
How can this corrected? How can i get IDEA to perform a static import?

Open the parentheses and you will get a prompt for statically importing the method. IntelliJ won't understand it's a method you're trying to reference until you add the parenthesis.
In other words, type assertThat( and then ALT-ENTER.

Related

Cannot resolve method 'getLifecycle' in 'Allure'

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

Guava Google using Reflections in java

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>

JUnit change class or method behaviour in integration tests

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.

Powermockito whenNew returns null if not matched

I do not know if it supposed to do that, but I guess not. Have a look to my code below.
File mocked = PowerMockito.mock(File.class);
PowerMockito.whenNew(File.class).withParameterTypes(String.class).withArguments(eq(THE_TARGET_PATH)).thenReturn(mocked);
File normalFile = new File(WORKING_PATH);
File mockedFile = new File(THE_TARGET_PATH);
I do expect that the normalFile will be created normally, but it is actually null. The mockedFile is mocked correctly btw.
I am also using #RunWith(PowerMockRunner.class) and #PrepareForTest({ClassWhereInstanceIsCreated.class, File.class})
and I am using:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
My finding shows that there is no good way to do partial constructor mocking with PowerMockito / PowerMockito 2. By the logic you should be able to do something like
PowerMockito.whenNew(File.class).withParameterTypes(String.class)
.withArguments(eq(WORKING_PATH)).thenCallRealMethod();
But this will trigger internal exception in the PowerMockito similar to this
org.mockito.exceptions.base.MockitoException: Cannot call abstract real method on java object! Calling real methods is only possible when mocking non abstract method. //correct example: when(mockOfConcreteClass.nonAbstractMethod()).thenCallRealMethod();
Thus, the only way I can see is to re-write the test. You should construct all your required File objects first, before mocking constructor and give PowerMockito rules which to return in each particualr case.
File mocked = Mockito.mock(File.class);
// create file as you want
File realFile = new File(WORKING_PATH);
// tell PowerMockito to return it
PowerMockito.whenNew(File.class).withParameterTypes(String.class)
.withArguments(Mockito.eq(WORKING_PATH)).thenReturn(realFile);
// tell PowerMockito to return mock if other argument passed
PowerMockito.whenNew(File.class).withParameterTypes(String.class)
.withArguments(Mockito.eq(THE_TARGET_PATH)).thenReturn(mocked);
File normalFile = new File(WORKING_PATH);
File mockedFile = new File(THE_TARGET_PATH);
This is undesirable solution, but I could not offer anything better.
Hope it helps!

Error when trying to use Guava FluentIterable with GWT

I'm trying to use Guava 12.0's FluentIterable with GWT 2.0.3, like so:
import com.google.common.collect.FluentIterable;
class FooPresenter {
// snip
private List<NullSafeCheckBox> asCheckboxes() {
return FluentIterable.from(getDisplay().getMetricInputs())
.transform(new Function<HasValueChangeHandlers<Boolean>, NullSafeCheckBox>() {
#Override
public NullSafeCheckBox apply(#Nullable HasValueChangeHandlers<Boolean> checkbox) {
return (NullSafeCheckBox) checkbox;
}
})
.toImmutableList();
}
}
However, when I run GWT in dev mode, I get the following error when trying to load the first module:
DEBUG: Validating newly compiled units
ERROR: Errors in 'jar:file:/home/josh/.m2/repository/com/google/guava/guava-gwt/12.0/guava-gwt-12.0.jar!/com/google/common/math/super/com/google/common/math/LongMath.java'
ERROR: Line 23: The import java.math cannot be resolved
My pom.xml looks like this:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>12.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-gwt</artifactId>
<version>12.0</version>
</dependency>
And my Application.gwt.xml sucks in Guava like this:
<!-- Guava -->
<inherits name="com.google.common.collect.Collect"/>
Update
Following the advice in Arcadian's answer, I added gwt-math to my pom.xml and my Application.gwt.xml:
<!-- Guava -->
<inherits name="com.google.common.collect.Collect"/>
<inherits name="com.googlecode.gwt.math.Math" />
Now I get this error when running hosted mode:
DEBUG: Validating newly compiled units
WARN: Warnings in 'jar:file:/home/josh/.m2/repository/videoplaza-third-party/gwt-incubator/20100204-r1747/gwt-incubator-20100204-r1747.jar!/com/google/gwt/widgetideas/client/impl/GlassPanelImpl.java'
WARN: Line 30: Referencing deprecated class 'com.google.gwt.user.client.impl.DocumentRootImpl'
WARN: Line 38: Referencing deprecated class 'com.google.gwt.user.client.impl.DocumentRootImpl'
ERROR: Errors in 'jar:file:/home/josh/.m2/repository/com/google/guava/guava-gwt/12.0/guava-gwt-12.0.jar!/com/google/common/primitives/UnsignedLong.java'
ERROR: Line 77: The method bitLength() is undefined for the type BigInteger
ERROR: Line 79: The method longValue() is undefined for the type BigInteger
ERROR: Line 200: The method valueOf(long) is undefined for the type BigInteger
ERROR: Line 202: The method setBit(int) is undefined for the type BigInteger
You can try to add gwt-java-math project as dependency. As said on their wiki,
This library is in the process of getting merged into GWT itself!
Currently it is on GWT trunk.
It may be available in the upcoming v2.5.
FYI, it looks to me like java.math should be available in current versions of GWT, though probably not in 2.0.3. See, e.g., the JRE emulation reference for GWT 2.2, probably the first version where it was available.
I don't know what to expect in combination with gwt-java-math; possibly Guava itself would need to declare a dependency on its module for it to work?
We do need to do a much better of of determining and advertising which version of GWT is required for Guava, including running our GWT tests against Guava (and not just our internal version of it) to verify that.

Categories