Override SLF4J implementation in unit tests for Android - java

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>

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).

"No junit.jar" error in Intellij when right clicking a folder, but not when running individual classes of tests

My Spring boot application has several tests classes.
When right-clicking a test class, and selecting the option to Run XYZtest it works with no problem.
But when selecting the folder that contains that class and selecting Run test in com.example.my I get an error of No junit.jar:
When running all the tests from mvn they run with no problems.
Following some suggestions, I added the junit.jar specifically in the Library section, but it didn't help:
Spring boot is using JUnit 5. If you use the spring boot initializr website, you should have a dependency like this.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
Did you use JUnit 4 or 5 in your tests ? You can try to update IntelliJ or JUnit plugin, this may solve your problem.
I met this problem, this is how I soloved it:
Context:
SpringBoot application
Use maven to manage multiple modules
Add junit's maven dependency in root POM's dependencyManagement(rather than dependencies, their differences can be found here)
Intend to test class or folder inside one of the root module's child module
PS: If your situation does not match the context above, this solution may not solve your problem.
Steps
right click at the class or folder you want to test:
Choose More Run/Debug -> Modify Run Configuration
Change the module option to the one you want to test from root module
I managed to solve the issue by adding the Junit Maven dependancy in the root pom.xml file.

Cannot import SpringApplicationContextLoader

I use IntelliJ IDEA and write Spring project.
I added dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
and more related to Spring Boot.
I cannot import SpringApplicationContextLoader using:
import org.springframework.boot.test.SpringApplicationContextLoader
But I see many projects on GitHub which use this class.
How can I check current package of this class?
According to javadoc of SpringApplicatioNContextLoader a.4.x it was deprecated in favor of #SpringBootTest or SpringBootContextLoader if absolutely necessary.
Solution provided by Yoav Gur doesn't work for the latest spring-boot (1.5.2.RELEASE).
In my case I was looking for a solution to activate a spring profile for my cucumber tests. And I too found a lot of solutions which import this SpringApplicationContextLoader.class.
There is a class SpringBootContextLoader which might substitute for this, but I found another solution for my issues so didn't use it.
In case you're interested, you can find it here:
How to activate spring boot profile with cucumber
Try adding the following dependency to your pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>1.1.1.RELEASE</version>
</dependency>
See:
https://1maven.com/idartifact/org.springframework.boot:spring-boot:1.1.1.RELEASE

JUnit5: Trouble Importing Assertions

I'm trying to use JUnit5 to create some basic unit tests. I go to my Analyzer.java class and get the popup for creating a test. I hit Create New Test, setting Testing Library to JUnit5. I check off a bunch of methods to generate test methods for and hit OK.
So now I have an AnalyzerTest.java file and at the top I have:
import static org.junit.jupiter.api.Assertions.*;
Unfortunately, Assertions is red (this is in IntelliJ IDEA). When I hover, it says "Cannot find symbol Assertions". In a similar vein, I have:
#org.junit.jupiter.api.Test
before each test method and when I hover, I get "Cannot resolve symbol Test"
I simply want to create and then run some unit tests but obviously am doing something wrong.
Any ideas?
Thanks!
Gradle
Add the following dependency to your Gradle:
testImplementation("org.junit.jupiter:junit-jupiter-api:5.0.1")
Under your dependencies.
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.0.1")
I don't know you are using or maven or gradle. But if you are using maven just add below dependecies in between your tags. Let me know if you need more help regarding this. I have used older version below, you can check the latest version from https://mvnrepository.com and update the pom script.
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
If you use IntelliJ-IDEA, make sure your test file is in the Test Sources roots.
Because my project do not have the path src/test/java, when I use Ctrl+Shift+T to add a test file, it added in src/main/java...
See intellij support post
Maven
If using Maven, be sure to specify a dependency element inside the dependencies element.
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.4.0-RC1</version>
<scope>test</scope>
</dependency>
If you want to use those Assertions outside of your test-related classes, in your regular app classes, drop the <scope>test</scope> element.
Note that as of 5.4.0 of JUnit, we can specify the new single Maven artifact of junitjupiter which in turn will supply 8 libraries to your project. Very convenient if you are writing only JUnit 5 tests (Jupiter test engine), and not “vintage” JUnit 4 tests or other test engines.
If using Gradle rather than Maven, see the Answer by RileyManda.

Mocking Firebase in JUnit

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.

Categories