Skip to content

Add support for including module-info in Mockito. #3597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Mar 3, 2025
Merged

Conversation

raphw
Copy link
Member

@raphw raphw commented Feb 23, 2025

Adds module-info.java to describe module descriptor.

Fixes #2604
Fixes #2952
Closes #3381

@raphw raphw mentioned this pull request Feb 23, 2025
8 tasks
@codecov-commenter
Copy link

codecov-commenter commented Feb 23, 2025

Codecov Report

Attention: Patch coverage is 78.04878% with 9 lines in your changes missing coverage. Please review.

Project coverage is 85.56%. Comparing base (d01ac9d) to head (5ca72f9).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...on/bytebuddy/InlineDelegateByteBuddyMockMaker.java 53.33% 7 Missing ⚠️
...ernal/configuration/plugins/PluginInitializer.java 83.33% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #3597      +/-   ##
============================================
- Coverage     85.60%   85.56%   -0.04%     
- Complexity     2956     2957       +1     
============================================
  Files           341      341              
  Lines          8995     9028      +33     
  Branches       1119     1119              
============================================
+ Hits           7700     7725      +25     
- Misses         1005     1013       +8     
  Partials        290      290              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@raphw
Copy link
Member Author

raphw commented Feb 24, 2025

I understand why this is failing now.

  1. We add the MockMethodDispatcher class to the org.mockito.internal.creation.bytebuddy.inject package.
  2. We compile the module-info.java where the compiler adds all packages in scope to the module's package list.
  3. Even though we remove the file later and rename it to raw, the package is still in the package list.
  4. The class loader never attempts to check another class loader (the boot loader) for this package. It is never found.

Could we "post-process" the module-info.class after the javac application? We could use ASM to apply a module visitor on it. All we would need to do would be to remove the package in question from the module info file.

@raphw
Copy link
Member Author

raphw commented Feb 24, 2025

This would be the code we need to run in the post-processing:

    ClassReader reader = new ClassReader("module-info.class");
    ClassWriter writer = new ClassWriter(reader, 0);
    reader.accept(new ClassVisitor(Opcodes.ASM9, writer) {
        @Override
        public ModuleVisitor visitModule(String name, int access, String version) {
            return new ModuleVisitor(Opcodes.ASM9, super.visitModule(name, access, version)) {
                @Override
                public void visitPackage(String packaze) {
                    if (!packaze.equals("org/mockito/internal/creation/bytebuddy/inject")) {
                        super.visitPackage(packaze);
                    }
                }
            };
        }
    }, 0);

@raphw
Copy link
Member Author

raphw commented Feb 24, 2025

@TimvdLippe Any idea how to effectivate this code? https://github.com/mockito/mockito/pull/3597/files

The Class writer returns a byte array that would need to replace the original file.

@raphw
Copy link
Member Author

raphw commented Feb 28, 2025

@TimvdLippe or @bric3 - I currently try to move the raw class file into a different folder (and therewith try to avoid that the class loader registers the package that this folder represents, so it can be loaded from the boot loader).

But this does not seem to work. I adjusted the copy task:

    from(sourceSets.main.flatMap { it.java.classesDirectory }
        .map { it.file("org/mockito/internal/creation/bytebuddy/inject/MockMethodDispatcher.class") })
    into(generatedInlineResource.map { it.dir("org/mockito/internal/creation/bytebuddy") })

    rename(".*", "inject-MockMethodDispatcher.raw")

Why does this not work? For me, the jar task fails now with:

Task :mockito-core:jar FAILED
error : Classes found in the wrong directory: {org/mockito/internal/creation/bytebuddy/MockMethodDispatcher.class=org.mockito.internal.creation.bytebuddy.inject.MockMethodDispatcher}

In short, I want the class to be stored as a file in the jar's org/mockito/internal/creation/bytebuddy/ folder, not in the org/mockito/internal/creation/bytebuddy/inject/ folder. And adjust the file name to append the inject and replace .class with .raw. The resulting jar must not contain the org/mockito/internal/creation/bytebuddy/inject/ folder altogether.

@TimvdLippe
Copy link
Contributor

You probably fixed the Jar task, as in the Gradle build scan (https://scans.gradle.com/s/x55h4q2hpkgeq/timeline?type=org.gradle.api.tasks.bundling.Jar#76bq4yvmlsst2) it is successful. Looking at the build failure, it seems to be an OSGi issue:

> Task :mockito-extensions:mockito-junit-jupiter:verifyOSGi FAILED
      ⇒ Bundle: org.mockito.junit-jupiter cannot be resolved
              ⇒ Import-Package: org.mockito.internal.configuration; version=[5.15.0,6.0.0); status=INTERNAL cannot be resolved
                      ⇒ because Import-Package requirement for: org.mockito.internal.creation.bytebuddy.inject could not be provided by any available bundle or dependency

We probably need to update our OSGi instead to ignore this error? A possible solution I found after googling this error: bndtools/bnd#2227 (comment)

tasks.jar {
    withConvention(BundleTaskConvention::class) {
        bnd(mapOf(
                "-fixupmessages" to "^Classes found in the wrong directory: \\\\{META-INF/versions/9/module-info\\\\.class=module-info}$"
        ))
    }
}

@raphw
Copy link
Member Author

raphw commented Mar 2, 2025

Indeed. I had to clean out my local build to get there.

I think I figured it out. Needed to fix some assumptions, but runs locally now. I think this does the trick altogether.

@TimvdLippe
Copy link
Contributor

Nice work! Glad to see we were able to figure it out together.

I do want us to see if we can find an alternative fix for our Javadoc though. I really do want us to omit our internal classes in our Javadoc as it is too easy to read over. With the fixes we made in Gradle, maybe we can add the line back and it "just" works?

@raphw
Copy link
Member Author

raphw commented Mar 3, 2025

I found a workaround where I define the sources explicily. It's a Gradle limitation as the missing packages still need to be included in the source task.

Copy link
Contributor

@TimvdLippe TimvdLippe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to see this all work and our Javadoc as well 🎉 I will publish a new minor release after this gets in

@TimvdLippe TimvdLippe merged commit c81be5d into main Mar 3, 2025
18 checks passed
@TimvdLippe TimvdLippe deleted the module-prototype branch March 3, 2025 10:11
@sormuras
Copy link

sormuras commented Mar 4, 2025

Nice 🧩 work!

svc-squareup-copybara pushed a commit to cashapp/misk that referenced this pull request Mar 4, 2025
| Package | Type | Package file | Manager | Update | Change |
|---|---|---|---|---|---|
| [org.mockito:mockito-core](https://github.com/mockito/mockito) |
dependencies | misk/gradle/libs.versions.toml | gradle | minor |
`5.15.2` -> `5.16.0` |
| [io.grpc:grpc-stub](https://github.com/grpc/grpc-java) | dependencies
| misk/gradle/libs.versions.toml | gradle | minor | `1.70.0` -> `1.71.0`
|
| [io.grpc:grpc-protobuf](https://github.com/grpc/grpc-java) |
dependencies | misk/gradle/libs.versions.toml | gradle | minor |
`1.70.0` -> `1.71.0` |
| [io.grpc:grpc-netty](https://github.com/grpc/grpc-java) | dependencies
| misk/gradle/libs.versions.toml | gradle | minor | `1.70.0` -> `1.71.0`
|
| [io.grpc:protoc-gen-grpc-java](https://github.com/grpc/grpc-java) |
dependencies | misk/gradle/libs.versions.toml | gradle | minor |
`1.70.0` -> `1.71.0` |
| [io.grpc:grpc-bom](https://github.com/grpc/grpc-java) | dependencies |
misk/gradle/libs.versions.toml | gradle | minor | `1.70.0` -> `1.71.0` |
| [io.grpc:grpc-api](https://github.com/grpc/grpc-java) | dependencies |
misk/gradle/libs.versions.toml | gradle | minor | `1.70.0` -> `1.71.0` |
|
[com.google.apis:google-api-services-storage](http://nexus.sonatype.org/oss-repository-hosting.html)
([source](http://svn.sonatype.org/spice/tags/oss-parent-7)) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`v1-rev20241206-2.0.0` -> `v1-rev20250224-2.0.0` |
|
[com.fasterxml.jackson.module:jackson-module-kotlin](https://github.com/FasterXML/jackson-module-kotlin)
| dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.18.2` -> `2.18.3` |
|
[com.fasterxml.jackson.datatype:jackson-datatype-jsr310](https://github.com/FasterXML/jackson-modules-java8)
| dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.18.2` -> `2.18.3` |
|
[com.fasterxml.jackson.dataformat:jackson-dataformat-yaml](https://github.com/FasterXML/jackson-dataformats-text)
| dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.18.2` -> `2.18.3` |
|
[com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson)
([source](https://github.com/FasterXML/jackson-databind)) | dependencies
| misk/gradle/libs.versions.toml | gradle | patch | `2.18.2` -> `2.18.3`
|
|
[com.fasterxml.jackson.core:jackson-core](https://github.com/FasterXML/jackson-core)
| dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.18.2` -> `2.18.3` |
|
[com.fasterxml.jackson:jackson-bom](https://github.com/FasterXML/jackson-bom)
| dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.18.2` -> `2.18.3` |
|
[com.fasterxml.jackson.core:jackson-annotations](https://github.com/FasterXML/jackson)
([source](https://github.com/FasterXML/jackson-annotations)) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.18.2` -> `2.18.3` |
| [software.amazon.awssdk:sdk-core](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.30.30` -> `2.30.32` |
| [software.amazon.awssdk:sqs](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.30.30` -> `2.30.32` |
|
[software.amazon.awssdk:dynamodb-enhanced](https://aws.amazon.com/sdkforjava)
| dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.30.30` -> `2.30.32` |
| [software.amazon.awssdk:dynamodb](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.30.30` -> `2.30.32` |
| [software.amazon.awssdk:aws-core](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.30.30` -> `2.30.32` |
| [software.amazon.awssdk:bom](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.30.30` -> `2.30.32` |
| [software.amazon.awssdk:auth](https://aws.amazon.com/sdkforjava) |
dependencies | misk/gradle/libs.versions.toml | gradle | patch |
`2.30.30` -> `2.30.32` |

---

### Release Notes

<details>
<summary>mockito/mockito (org.mockito:mockito-core)</summary>

### [`v5.16.0`](https://github.com/mockito/mockito/releases/tag/v5.16.0)

<sup><sup>*Changelog generated by [Shipkit Changelog Gradle
Plugin](https://github.com/shipkit/shipkit-changelog)*</sup></sup>

##### 5.16.0

- 2025-03-03 - [10
commit(s)](mockito/mockito@v5.15.2...v5.16.0)
by Brice Dutheil, Rafael Winterhalter, TDL, dependabot\[bot]
- Add support for including module-info in Mockito.
[(#&#8203;3597)](mockito/mockito#3597)
- Bump com.gradle.develocity from 3.19 to 3.19.1
[(#&#8203;3579)](mockito/mockito#3579)
- Bump org.assertj:assertj-core from 3.27.2 to 3.27.3
[(#&#8203;3577)](mockito/mockito#3577)
- Bump com.diffplug.spotless:spotless-plugin-gradle from 7.0.1 to 7.0.2
[(#&#8203;3574)](mockito/mockito#3574)
- Bump com.diffplug.spotless:spotless-plugin-gradle from 6.25.0 to 7.0.1
[(#&#8203;3571)](mockito/mockito#3571)
- Bump org.assertj:assertj-core from 3.27.1 to 3.27.2
[(#&#8203;3569)](mockito/mockito#3569)
- Tweaks documentation on mockito agent config for maven
[(#&#8203;3568)](mockito/mockito#3568)
- Adds `--info` to diagnose closeAndReleaseStagingRepositories issues
[(#&#8203;3567)](mockito/mockito#3567)
- Refine reflection when calling management factory
[(#&#8203;3566)](mockito/mockito#3566)
- Avoid warning when dynamic attach is enabled
[(#&#8203;3551)](mockito/mockito#3551)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 6pm every weekday,before 2am
every weekday" in timezone Australia/Melbourne, Automerge - At any time
(no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://github.com/renovatebot/renovate).

GitOrigin-RevId: b36ad622d93f38a65018855e51bd093a591e512b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Could not initialize inline Byte Buddy mock maker Consider adding module-info.class
4 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy