Search code examples
javaunit-testingjenkinsmockitojunit5

Multiple tests fail when ran on Jenkins after migration


I recently migrated a Unit Testing suite to Junit 5.8.2 and Mockito 4.5.1 + Mockito Inline to allow static mocking. Powermock was removed.

2000+ tests were migrated and they all run successfully when ran inside the IDE (IntelliJ). Both with the IDEA and Gradle runner.

However, when Jenkins attempts to run them there are over 900 failed tests. Some of the exceptions thrown.

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);
org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
Boolean cannot be returned by someMethod()
someMethod() should return Date`

I understand what causes these errors as I've seen them multiple times during the migration so this is not a duplicate asking for the solution.(Unless there's something different with the Jenkins environment) The code that throws such exceptions should not be throwing them. And it does not in the IDE. It's thrown exclusively in Jenkins.

An additional exception which I have never seen before is thrown as well.

org.mockito.exceptions.misusing.UnfinishedMockingSessionException: 
Unfinished mocking session detected.
Previous MockitoSession was not concluded with 'finishMocking()'.
For examples of correct usage see javadoc for MockitoSession class.

Most of the exceptions are of this type. However, the MockitoSession inteface is not used anywhere in the test suite. All mocks are initialized with @ExtendWith(MockitoExtension.class)

I have no idea what could be causing this.

Jenkins is running the same versions of Java/Junit/Mockito/Spring as the code in the IDE. It seems clear to me that the different environments are causing the issue. However, what could be the difference and how would I go about finding it?

I attempted to reproduce the results locally but was unable to. Any ideas towards that are also welcome.


Solution

  • Figured out what was happening.

    We tried to mockStatic() a few methods.

    However, those methods would call a few classes that contained static fields/methods that were NOT statically mocked because they were so deep in spaghetti, we didn't even realized the flow of code was getting there.

    Some of those static methods would contact the DB and pull information from there that would then be used inside the unit tests.

    When ran locally, that did not present any problem as every dev had a local database and the connection was successful.

    The Jenkins environment however didn't have a DB so when the static methods initialized and attempted to connect, a DB connection exception was thrown.

    However, as mentioned, that exception was thrown inside a try-with-resources mockStatic() block and since the static mocking did not complete, any subsequent attempt to mockStatic() the class that previously failed, would result in the aforementioned UnfinishedMockingSessionException.

    The solution was to find the statically mock any method that would attempt to communicate with the Database.

    What I still don't understand is why would an exception being thrown inside a try-with-resources mockStatic() block would prevent any subsequent attempts. In my understanding it should have been localized. The exception thrown was masking the real problem.

    In any case, I don't work there nor care anymore.