Mocking Firebase in JUnit - java

I'm writing a Java application that makes use of Firebase and the RealtimeDB.
While writing my unit tests, I ran into a rather strange issue in that the Firebase classes can not be loaded inside JUnit, throwing a NoSuchMethodError:
java.lang.NoSuchMethodError: com.google.common.primitives.UnsignedInteger.asUnsigned(I)Lcom/google/common/primitives/UnsignedInteger;
I've managed to track it down to Firebase using a different Guava version than the rest of the project, but even though I've forced the use of Guava 19.0 (through the Maven dependency exclusion mechanism), I'm still getting the same error, apparently when the FirebaseOptions class is being loaded (exact location: com.google.firebase.FirebaseOptions$Builder.setServiceAccount(FirebaseOptions.java:77)).
EDIT:
The problem only appears during a test run, at run-time, the Guava library is loaded correctly.
Does anyone have any ideas on how to provide Firebase with the Guava library properly?

Apparently, the solution was to add the resolution exclusion to the POM (making the final dependency as follows
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-server-sdk</artifactId>
<version>[3.0.0,)</version>
<exclusions>
<exclusion>
<groupId>guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
), then force a purge of the local repository. After re-indexing the project, the test were able to load the appropriate classes without issues.

Related

How to solve my dependencies problem using Maven and slf4j with OWLAPI on Eclipse please

First of all, I'm a newbie with Maven, so I apologize if I misunderstood something.
In a recent question I ask about the import of OWLApi in my Java project and people told me to use Maven to import it, instead of importing JAR file.
I tried a new Maven Project and imported to test OWLApi and it worked well.
Today, for my profesionnal project, I managed to work with Maven. I converted my project to Maven, added OWLApi in my dependencies... and when I build with Maven, I got the error :
Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError
Moreover, my classes are not compiled anymore (impossible to run my classes, because no .class are compiled).
If it helps, this is my pom, where I tried to excluse slf4j, as I found in another question. But it didn't help me :
<dependencies>
<dependency>
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>owlapi-distribution</artifactId>
<version>5.0.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Thank you in advance.
What's happening here is that the classpath contains two adapters, one that passes logging calls done with Log4J to a SLF4J logger, and one that does exactly the reverse. With both in the classpath, any logging call would go first to one logging system, then be passed to the other, and this would create an infinite loop. This would result in a stack overflow, which is what the error message is reporting.
OWLAPI doesn't import either jar, it only imports the SLF4J API, so the conflicting jars must be dependencies of other libraries.
You have tagged Eclipse here, so I assume you're using Eclipse. When you open a pom file in Eclipse, you get a tabbed editor, with one tab being Dependency Hierarchy. You can use this tab to look for the jars you wish to exclude, the tab will show which of your dependencies are bringing in the jars, so you can put the exclusions in the right place. It should be sufficient to exclude one of the jars (it depends on which logging system you mean to actually use).

Spring, Maven: Correct the classpath of your application

I am trying to create a maven version of the gradle-based treehouse 'unit-testing-a-spring-application' project used in this course. See course code here.
After not being able to build initially, I ended up adding dependency versions specified in the original gradle build file. Maven will build fine, but running the app gives this:
The following method did not exist:
org.springframework.data.repository.config.RepositoryConfigurationSource.getAttribute(Ljava/lang/String;)
Ljava/lang/String;
The method's class, org.springframework.data.repository.config.RepositoryConfigurationSource, is
available from the following locations:
jar:file:/C:/Users/home/.m2/repository/org/springframework/data/spring-data-
commons/2.1.6.RELEASE/spring-data-commons-2.1.6.RELEASE.jar!/org/springframework/data/repository/config/RepositoryConfigurationSource.class
It was loaded from the following location:
file:/C:/Users/home/.m2/repository/org/springframework/data/spring-data-commons/2.1.6.RELEASE/spring-
data-commons-2.1.6.RELEASE.jar
Action
Correct the classpath of your application so that it contains a single, compatible version of
org.springframework.data.repository.config.RepositoryConfigurationSource.
Several similar problems are solved here on S.O. by changing the version of some related dependency. I have tried various versions of the following to no avail (I stick normally with spring-boot-starter-parent v2.1.4 cause it works all the time with my projects):
spring-data-commons
spring-boot-starter-parent
I see the needed class below listed in my project Dependencies directory, but what dependency versions will work in this case? How can I solve this otherwise?
org/springframework/data/repository/config/RepositoryConfigurationSource.class
I looked at your code and found some mistakes. Since your project is a spring-boot one, you mustn't add direct spring dependencies in your pom file. Instead try to use spring-boot based dependencies. For instance, instead of having such this dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.2.RELEASE</version>
</dependency>
You must have the following one in your pom file.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

copyInputStreamToFile method does not exist

I'm trying to use the copyInput method in my code, but seems like Intellij told me that the method does not exist
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), downloadedFile);
I'm using the code from here
http://ardesco.lazerycode.com/index.php/2012/07/how-to-download-files-with-selenium-and-why-you-shouldnt/
But it seems like the method exist here
https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/FileUtils.html
I'm using maven, I tried with 2.0, 2.1, 2.4 without luck
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.2</version>
</dependency>
Java 1.8
Here is the error message
Error:(201, 22) java: cannot find symbol
symbol: method copyInputStreamToFile(java.io.InputStream,java.io.File)
location: class org.apache.commons.io.FileUtils
You probably have another (older) org.apache.commons.io.FileUtils on your classpath, which would explain the issues you're having. Most likely one of your dependencies has an old org.apache.commons:commons-io artifact on the classpath. Due to the groupId difference, Maven considers them different artifacts and puts both on the classpath.
If that is what's really happening, you can explicitly forbid maven from including this transitive dependency by adding an exclusion to the dependency that references the old commons-io (even if it depends on it transitively):
<dependency>
<groupId>offending.artifact.groupId</groupId>
<artifactId>offending.artifact.artifactId</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
</exclusion>
</exclusions>
</dependency>
I was able to see the wrong version using the menu options "To find the offending class in IntelliJ IDEA: Menu > Navigate > Class > type FileUtils", there were like 4 FileUtils,
I imported the correct version on the jar file and it fix the problem, Thanks #Anton.
FileUtils.copyInputStreamToFile(inputStream,file);
This function may be used in versions larger than two (2). You need to add this line to the gradle:
implementation 'org.apache.directory.studio:org.apache.commons.io:2.4'
I got the same problem, but it seems that I had old version of version of commons-io. I fixed it by changing version to 2.6 in pom.xml file.

Override SLF4J implementation in unit tests for Android

How to override SLF4J implementation for unit tests?
For Android application im using:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-android</artifactId>
<version>1.6.1-RC1</version>
</dependency>
But unfortunately, running any unit test gives me:
java.lang.RuntimeException: Stub!
Due to stubbed Android JAR's in Maven Central.
I have a lot of utility and tiny service classes which don't use Android API. But some of them use slf4j logger's which causes this error.
How can i test them without splitting classes into two separate artifacts?
The way which i currently use is to remove slf4j-android and add slf4j-simple in test scope.
I found that i can configure Maven surefire plugin:
<configuration>
<classpathDependencyExcludes>
<dependencyExclude>org.slf4j:slf4j-android</dependencyExclude>
</classpathDependencyExcludes>
</configuration>
But IDE... No... Looks like IntelliJ IDEA silently ignores this setting and run tests with slf4j-android.
Similar question:
Alternate SLF4J Binding or Config For Unit Test?
But not suitable for slf4j-android.
Maybe somebody knows more convenient and working solution for this problem?
Maybe use another logging framework. But i don't know any other which works well with Android.
BTW: Robolectric didn't help.
Not perfect solution - workaround
In my project I have separated application logic (my-app-library) and unit tests (my-app-test) into two different modules. With this configuration I can test logic from my-app-library with standard logger.
Configuration from my-app-test:
<dependency>
<groupId>my.android.app</groupId>
<artifactId>my-app-library</artifactId>
<version>1.2.5-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-android</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>

Difference between ehcache and ehcache-core

I am beginner for ehcache v/s ehcache-core in Spring framework, my pom.xml used ehcache version 1.5.0
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>1.5.0</version>
</dependency>
Now, it will need to update ehcache version because it will use in another jar:-
Updated ehcache version 2.7.0
But it returns error
net.sf.ehcache.Cache.getStatistics() method not found.
Now, I am replacing ehcache via ehcache-core 2.5.7 as:-
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.5.7</version>
</dependency>
Is it break another functionalities or will work same as ehcache?
Just as many other large frameworks (like Spring), ehcache is split into several modules. One of those modules is core, the others are web, server, jcache, debugger and many more (see https://mvnrepository.com/artifact/org.ehcache.modules).
Sometimes, for various reasons, you may not want to include the entire large framework, with all its sublibraries, into your project. Then you can decide which module you want to use.
In other words, using ehcache pom will include a full library in your project. Using ehcache-core will only include functionalities defined in ehcache-core.
You can either find out which module contains the functionality you need and include it, or go with full ehcache but use the appropriate version.
There still is an ehcache module in version 2.5.7 but as it only pulls dependencies it's of type pom. One of those dependencies is ehcache-core. My guess is that your functionality won't be satsified with just that. Try
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.5.7</version>
<type>pom</type>
</dependency>

Categories