Mockito fails in Maven but succeeds in Eclipse - java

We have a test wich fails when executed in Maven, but succeeds in Eclipse.
Basically the problem is, that when executed with Maven Mockito fails to mock a method which comes from a superclass from another maven module with package private modifier.
Questions
Why is this so?
Is this a known bug? If not where to file it? surefire, mockito ...?
how to fix it?
I have found a description of a similar problem, with the recommended fix to use surefire-2.7.1 instead of 2.7.0 but we are already on 2.10 (and also see the problem in 2.16)
Obviously the simplest solution would be to make the BaseClass public, but we can't do it, since it is not under our control.
Another alternative would be to overwrite close in MockedClass, which would be ugly but possible.
The error message is
failsCallingOriginalMethod(ModifierTest) Time elapsed: 0.156 sec <<< ERROR!
java.lang.RuntimeException: must not have called me
Relevant Code
The real code is not in the default package, but all code is in the same package; import statements removed for brevity.
Maven Module 1
public class ModifierTest
{
#Test
public void failsCallingOriginalMethod()
{
MockedClass mock = Mockito.mock(MockedClass.class);
doNothing().when(mock).close();
}
}
Maven Module 2
public class MockedClass extends BaseClass
{
}
class BaseClass
{
public void close()
{
throw new RuntimeException("must not have called me");
}
}
Versions of stuff involved
Maven Version 3.0.5 (can't change that due to other bugs)
Oracle JDK 1.6.0_20 (reproducable with IBM JDK 1.5)
Mockito 1.95
surefire plugin 2.10 (reproducable with 2.16)

Do you have control over MockedClass?
If so, you could consider adding a delegating method in MockedClass:
public void close() {
super.close();
}
This doesn't solve the issue, but it's a quick workaround.

Related

How to re-run only fail tests? (I use junit5+maven+springboot)

run only fail test but after all build work
This is my fail test case
ExempleIT extends BaseIT {
#Test
public void testfailure(){
Assertions.assertTrue(false);
}
and this is my base test class
#ExtendWith({SpringExtension.class})
#SpringBootTest()
public abstract class BaseIT { ...
I tried
maven -Dfailsafe.skipAfterFailureCount=1 -Dfailsafe.rerunFailingTestsCount=2
and surefire but these does not support junit5
I rerunner-jupiter but this supports only method base but I want to use base class for all tests and after all build, Which other way can I follow?
Check this answer.
The maven-surefire-plugin, as of today, does not have full support of JUnit 5. There is an open issue about adding this support in SUREFIRE-1206.
As such, you need to use a custom provider.(...)
This info is from an old post.
The existing limitation with maven-surefire is related only with some features on JUNIT5.

Mockito : doNothing tries to invoke the void method in Android instrumented test

EDIT
When reading the FAQ, it gave me some idea about what could possibly cause an issue here. Just to give it a try, I changed the visibility of the stubbed method open() to public and it was executed as expected, without any exception thrown.
I'm not sure if it's a bug or the desired behaviour of version 1.10.19.
ORIGINAL POST
In my Android project, I'm using Mockito to ease the implementation of some (instrumentation) tests. I was able to mock some non-void methods, but didn't figured out how to properly stub a void method.
I'm trying to test a class House. A House has an attribute of type Door and a method openDoor(). A Door and an attribute of type Handle and a method open(). When I invoke the openDoor(), I would like to check if open() was called, so I wrote this code:
#Test
public void testOpenDoorInitial() {
Door stubbedDoor = mock(Door.class);
doNothing().when(stubbedDoor).open();
myHouse.setDoor(stubbedDoor); //myHouse has been initialized
myHouse.openDoor();
verify(stubbedDoor, times(1)).open();
}
public class House {
Door door;
//rest of code
void setDoor(Door d){
door = d;
}
void openDoor(){
// some conditions
door.open();
}
}
public class Door {
Handle handle;
//... rest of code
void open(){
handle.tryToUse(); //Throws NullPointException
}
}
The problem is that a NullPointerException is thrown on line doNothing.when(stubbedDoor).open();, telling me that handle is null. doNothing() seems to actually call open(), which I don't expect.
Does anyone has an idea about the source of this problem ? I'm new to Mockito, so I could have missed something obvious.
To enable Mockito in instrumentation testing, I imported the following modules.
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile "com.crittercism.dexmaker:dexmaker:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-dx:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-mockito:1.4"
Try to use a newer version, you are using 1.10.19. I am not sure but it seems this issue was solved after, as you can see here.
Here you can find the version list.
This may be related to Mockito's issue 212, in which package-private parent classes can cause mocks to fail because Mockito couldn't stub the hidden methods. (This may be related to synthetic methods that the compiler introduces to work around visibility complications in the class hierarchy.)
Mockito 2.0 solves this problem by switching from CGLIB to ByteBuddy; I don't remember whether ByteBuddy was a part of any 1.x release. However, you're using Mockito with DexMaker instead, which may have a similar problem.

Order of imports seems to matter for compilation to succeed?

I'm writing a unit test for some Java class in Eclipse. I always let Eclipse handle my imports automatically, and it orders them according to whatever default scheme.
Now, I have the following situation. The unit test builds and runs just fine in Eclipse. However, when I build the tests on the command line (using some Ant targets), javac complains that it can't find one of the classes I've imported. Since I'm testing something with caching, the relevant bits of the test file (Test.java let's say) are:
import com.abc.my.stuff.MyCacheLoader.Operation;
import com.google.common.cache.CacheLoader;
public class Test {
... test code, such as ...
List<MyKey> recordedKeys = dummyLoader.getKeysFor(Operation.LoadAll);
}
// Dummy cache loader which just records the keys
class MyCacheLoader extends CacheLoader<MyKey, MyValue> {
enum Operation { Load, LoadAll }
#Override
public MyValue load(MyKey key) throws Exception { .... whatever .... }
#Override
public MyValue loadAll(Iterable<MyKey> key) throws Exception { .... whatever .... }
public List<MyKey> getKeysFor(Operation op) { ... impl ... }
}
Notice that the import for my local class's inner enum appears before the import for the Guava CacheLoader class, because they are ordered alphabetically. When I try to compile this using Ant on the command line, javac can't find 'CacheLoader'. When I switch the order of the imports, the build succeeds (whereas Eclipse doesn't care either way).
I'm mystified as to what's going on here.
Apparently, the compiler in Eclipse doesn't have the following Sun bug:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6391197
which I found via:
http://unimplemented.blogspot.com/2007/08/my-java-puzzle-does-order-of-import.html
This explains why flipping the order of imports makes no difference to Eclipse, but it does to the Sun compiler. Part of the problem is fixed in Java 8, but my particular manifestation is targeted for a fix in Java 9: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7101822

Why/how does JUnit pass tests with compiler errors?

I've just started learning about TDD and am trying to write a simple project that way.
I'm using Eclipse and JUnit, and every time I make a change I run all the tests in the relevant package.
But then I'm very surprised to see in the package explorer that one of my test cases has a big red cross indicating a compiler problem... Annoyed I figured that I got my eclipse shortcuts mixed up and haven't been running all the tests, as they are all passing.
But when I start fiddling about, I realise that it seems Eclipse + JUnit will run and pass tests even if there are compiler errors...
The JUnit test case:
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class ATestCase {
private Command command;
private Invoker invoker;
#Before
public void setUp() throws Exception {
command = new Command() {
public void methodA(){};
//haven't implemented methodB()
};
invoker = new Invoker(command);
}
#Test
public void test(){
invoker.invoke();
}
}
interface Command{
void methodA();
void methodB();
}
The Invoker class:
class Invoker{
private Command command;
public Invoker(Command command) {
this.command = command;
//if I invoke methodB() I get UnresolvedCompilationError
}
public void invoke(){
command.methodA();
//only if I call methodB here
//do I get Unresolved compilation problem
// command.methodB();
}
}
The command object I create in setUp in the test case only implements one of the interface's methods. This of course causes a compilation error warning in Eclipse.
However unless I actually call that method in the test case, the test passes.
If I do call the method, then the test fails with 'unresolved compilation error'.
Can anyone explain to me what exactly is going on?
******EDIT******
I'm not sure why this was closed as a duplicate.
Apparently I'm supposed to edit this question to make the difference clear:
Well the question I'm supposed to be duplicating asks in the first line:
What are the possible causes of a "java.lang.Error: Unresolved
compilation problem"?
The title of my question states I'm asking:
Why/how does JUnit pass tests with compiler errors?
As in how can code which shouldn't compile be run by JUnit without causing errors?
I fully understand the causes of the Unresolved Compilation Error, it's the obvious unresolved compilation error in my code. What I don't understand is how the error doesn't always occur (it only occurs when I specifically call an unimplemented method) and how the tests pass?!
It may be that these issues are related, but unless there is a specific answer explaining how they are related I fail to see how they are in any way duplicate questions...
When a class fails to implement an interface method, the Java compiler does not reject the code but instead emits bytecode for the method that will raise the runtime error seen. This explains why JUnit is able to run the tests and why the test passes if you don't call methodB - the runtime error does not get raised.
Per this page, this does not occur by default but requires that you have the Java -> Debug 'Suspend execution on compilation errors' setting enabled.
I'm assuming that is by design: to allow for testing specific methods without having to worry about whether other dependencies which the compiler would pick up on anyway are resolved or not. i.e. we shouldn't be using JUnit to tell us whether our entire project can compile or not.

Unrooted Tests

When running all my tests in Eclipse (Eclipse 3.4 'Ganymede'), one test is listed under "Unrooted Tests". I'm using Junit 3.8 and this particular test extends TestCase. I do not see any difference between this test and the other tests. I don't remember seeing this occur in Eclipse 3.3 (Europa).
Clarification:
We haven't moved to JUnit 4.0 yet, so we are not using annotations. I also googled and it seemed like most people were having issues with JUnit 4, but I did not see any solutions. At this point the test passes both locally and in CruiseControl so I'm not overly concerned, but curious.
When I first saw this, though, it was on a failing test that only failed when run with other tests. This led me down the rabbit hole looking for a solution to the "Unrooted" issue that I never found. Eventually I found the culprit in another test that was not properly tearing down.
I agree, it does seem like an Eclipse issue.
Finally I found the solution. The problem is that you are not defining your test cases using annotations but are still doing it the "old way". As soon as you convert over to using annotations you will be able to run one test at a time again.
Here is an example of what a basic test should now look like using annotations:
import static org.junit.Assert.*; // Notice the use of "static" here
import org.junit.Before;
import org.junit.Test;
public class MyTests { // Notice we don't extent TestCases anymore
#Before
public void setUp() { // Note: It is not required to call this setUp()
// ...
}
#Test
public void doSomeTest() { // Note: method need not be called "testXXX"
// ...
assertTrue(1 == 1);
}
}
I was getting the "unrooted tests" error message as well and it went away magically. I believe it was due to the fact that I was using Eclipse with a Maven project. When I added a new method to my Test class and gave it the #Test annotation, it began getting the error message when I tried to run that one method using the "Run as Junit test" menu option; however, once I ran a maven build the unrooted tests message disappeared and I believe that is the solution to the problem in the future.
Run a maven build because it will refresh the class that JUnit is using.
If your class extends TestCase somewhere in its hierarchy, you have to use the JUnit 3 test runner listed in the drop down under run configurations. Using the JUnit 4 runner (the default I believe) causes that unrooted test phenomenon to occur.
I got this error because I renamed my test method and then tried to run the test in Eclipse by clicking on the same run configuration - referring to the old method which now didn't exist.
We solved the problem by making sure our test project was built. We had an issue in the build path which would not allow our test class to be compiled. Once we resolved the build path issue, the test compiled and the "new" method was able to be run. So we can assume that "Unrooted" tests also mean that they don't exist in the compiled binary.
I've never seen this -- but as far as I can tell from skimming Google for a few minutes, this appears as though it could be a bug in Eclipse rather than a problem with your test. You don't have the #Test annotation on the test, I assume? Can you blow the test away and recreate it, and if so do you get the same error?
Another scenario that causes this problem was me blindly copy/pasting a method that requires a parameter. i.e.
import org.junit.Test;
public class MyTest {
#Test
public void someMethod(String param) {
// stuff
}
}
You have a few simple solutions:
define the variable in the specific test method
add it as an instance variable to the test class
create a setup method and annotate it with #Before
For me, it was due to the project got build path issues. My maven dependencies configuration needs to be updated.
I had that problem and putting one "#Test" before the test method solved it!
like this:
#Test
public void testOne() { // ...
assertTrue(1 == 1);
}
These are the two scenarios that the Unrooted errors show up.
If you have missed the annotation #Test before the test.
#Test
public void foo(){
}
If it is a Gwt project and when two mock of the same object are defined. Lets say there is one class Class A and
#GwtMock
private A atest;
#GwtMock
private A a;
Then this will also show a Unrooted test error.
One other thing you can try is to upgrade your version of JUnit to at least 4.12.
I was experiencing this problem for a while with a class that extended one that used #RunWith(Parameterized.class).
After a while, and I'm sorry that I don't know precisely what I did to cause this, the 'Unrooted Tests' message went away, but the test still didn't run correctly. The constructor that should have accepted arguments from the #Parameters method was never getting called; execution jumped straight from #BeforeClass to #AfterClass.
The fix for that problem was to upgrade JUnit from the 4.8.1 it was using, to the latest (4.12). So maybe that could help someone else in the future.
I had the same problem with
java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
you need the jar hamcrest.
same question 14539072: java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
I could the fix the issue by shifting from TestRunner ver 4.0 to 3 in run configurations for the individual test method.
Do not extend junit.framework.TestCase in your test class with junit1.4 and this should solve the problem
You are using Hamcrest? or another library to help in your test?. You are not using
import static org.junit.Assert.*;
Check if in your test you use:
import static org.hamcrest.MatcherAssert.assertThat;
or other assert isnĀ“t JUnit assert.
It turned out to be that my build path had some error...some jars were missing.
I reconfigured build path and it worked!
For me the problem was, that an exception was thrown in the #BeforeClass or #AfterClass methods. This will also cause tests to be categorized as unrooted.
I got this error with the test method name as "test"
#Test
public void test() {
// ... assertTrue(1 == 1);
}
I renamed the method and it worked
I ran into this problem by not also declaring the test to be static.
Maybe it's just a logical confusion about the goal of the method. Let's remember:
E.g. correct tagged test method:
#Test
#Transactional
#Rollback(true)
public void testInsertCustomer() {
(...)
}
-With Eclipse Junit plugin, You can run that test method using context menu over the method (E.g. at package explorer expanding the class and methods and selecting "testInsertCustomer()" method and from that item selecting "Run as >> JUnit test").
If you forgot "#Test" tag, or simply the method is not a test, but a (private or not) common method for using as utility for the other tests (e.g. "private fillCustomerObject()"), then the method does not require "#Test" tag, and simply you can not run it as a JUnit test!
It's easy that you could create a utility method and later you forgot the real goal of that method, so if you try to run it as a test, JUnit will shout "Unrooted Tests".
For me this problem was created by a real-time exception thrown in the #AfterClass method (take a look here for documentation):
Basically all the test methods succeeded but at the end of the class this method was failing. Therefore all the tests seems fine but there was on my Eclipse an additional "unrooted test" failed.
I got these errors for a maven project. I rebuild the project with mvn clean install.And the issue was solved
It actually told me there is a test with annotation: #RunWith(MockitoJUnitRunner.class)

Categories