0

I am using mockito-core dependency version 3.6.0 using maven as our dependency manager. I observed that same versioned mockito-core used to come with 'compile' dependency scope for 'objenesis' jar

+- org.mockito:mockito-core:jar:3.6.0:test
[INFO] |  +- net.bytebuddy:byte-buddy:jar:1.10.11:test
[INFO] |  +- net.bytebuddy:byte-buddy-agent:jar:1.10.11:test
[INFO] |  \- org.objenesis:objenesis:jar:3.1:compile

but all of sudden it has changed the scope to 'test' for 'objenesis'

+- org.mockito:mockito-core:jar:3.6.0:test
[INFO] |  +- net.bytebuddy:byte-buddy:jar:1.10.11:test
[INFO] |  +- net.bytebuddy:byte-buddy-agent:jar:1.10.11:test
[INFO] |  \- org.objenesis:objenesis:jar:3.1:test

This has obviously caused significant issues to dependency injections in our application because we used cglib to create proxy for beans.

What could have caused the change of scope for the same versioned dependency of mockito-core?

Vishal
  • 666
  • 1
  • 8
  • 30
  • It can only changed in case someone changed something...check your version control... – khmarbaise Jan 19 '22 at 09:08
  • I checked the version control, nothing suspicious to me. But even if I have changed dependencies in my codebase, how can it change transitive scope of mockito-core dependencies? – Vishal Jan 19 '22 at 09:35
  • If you define the dependency with a particular scope in your own pom ... furthermore that sounds like that you are using classes from objenesis directly but not defining a direct dependency to that artifact... which I would suggest to do. It's also possible that some of your own dependencies changed ... without the full project pom file etc. it's hard to say... – khmarbaise Jan 19 '22 at 09:57

2 Answers2

1

Mockito-core declares objenesis in compile scope because it needs it to compile. However, when you add mockito-core in test scope to another project, all these compile scope dependencies become test scope.

However, if you have objenesis somewhere else in compile scope and in a lower version than mockito-core, objenesis will turn back to compile scope and the one from mockito-core being a higher version, that's the selected one.

One solution to find out who is providing this other objenesis, is to exclude objenesis from mockito-core and check where it appears in the dependency:tree.

Objenesis is frequently used in compile scope. By Spring for instance. You can add an explicit objenesis dependency in runtime scope to get the correct scope from the point of view of your project. Like many other dependencies that are not directly used by your project. But keeping that clean is a lot of work.

You can see this effect by looking at this sample project.

Henri
  • 5,551
  • 1
  • 22
  • 29
  • " if you have objenesis somewhere else in compile scope and in a lower version than mockito-core, objenesis will turn back to compile scope and the one from mockito-core being a higher version, that's the selected one" , this is a new thing to learn today about scopes @Henri. Could you please point me to its documentation? Can't find the explanation on maven – Vishal Jan 21 '22 at 16:17
  • Here is a demonstration: https://github.com/henri-tremblay/maven-scope – Henri Jan 22 '22 at 20:52
0

The output from the dependency:tree goal can be very misleading: it outputs details are based on Maven's internal representation of the resolved dependencies, and only lists each dependency once, even if those dependencies are include via multiple paths. Better visualisations are available, such as in your favourite IDE.

I'm not sure exactly what happened to cause your issue, but it probably isn't related to a change in Mockito: if you have a test-scope dependency on a module, then its compile-scope dependencies are transitively included as test-scope into your project. The exact configuration displayed by in your question is not possible in Maven (it's just a misleading output from dependency:tree). It's likely that some other compile-scope dependency also had a dependency on objenesis, and it's that other dependency that has been removed or changed, and no longer has that dependency.

If you depend directly on a dependency, you should declare it as a dependency in the appropriate POM, and not rely on it being transitively included by an unrelated dependency. You should make sure that whichever component needs objenesis directly has a compile (or runtime) scope dependency on objenesis.

Jelaby
  • 1,107
  • 1
  • 9
  • 19