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
Mocking static methods not working anymore since version 4.2.0 #2530
Comments
Hey @TimvdLippe , I think it is related to our recent changes here: #2506. Not sure what is happening, but it is related to
|
try either dropping this argument:
or specify the default as the return type you need:
|
Dropping the second parameter fixes the issue of the example with FooUtils, but in some cases I need to partially mock and therefor need the second parameter. I have couple of uses cases here:
I have copied one of the unit tests of the project below: @Test
void getRootCaIfPossibleReturnsJdkTrustedCaCertificateWhenNoAuthorityInfoAccessExtensionIsPresent() {
List<Certificate> certificates = CertificateUtils.getCertificate("https://www.reddit.com/")
.get("https://www.reddit.com/");
try (MockedStatic<CertificateUtils> certificateUtilsMockedStatic = mockStatic(CertificateUtils.class, invocation -> {
Method method = invocation.getMethod();
if ("getRootCaFromAuthorityInfoAccessExtensionIfPresent".equals(method.getName())) {
return invocation.getMock();
} else {
return invocation.callRealMethod();
}
})) {
certificateUtilsMockedStatic.when(() -> CertificateUtils.getRootCaFromAuthorityInfoAccessExtensionIfPresent(any(X509Certificate.class)))
.thenReturn(Collections.emptyList());
X509Certificate certificate = (X509Certificate) certificates.get(certificates.size() - 1);
List<X509Certificate> rootCaCertificate = CertificateUtils.getRootCaIfPossible(certificate);
assertThat(rootCaCertificate).isNotEmpty();
certificateUtilsMockedStatic.verify(() -> CertificateUtils.getRootCaFromJdkTrustedCertificates(certificate), times(1));
}
} The error message for the above test is:
Any idea why the above one could be failing? |
I tried to add a cast to the returned object for the mocked one and then it passes. So I added: So the following test passes when having a explicite cast: @Test
void getRootCaIfPossibleReturnsJdkTrustedCaCertificateWhenNoAuthorityInfoAccessExtensionIsPresent() {
List<Certificate> certificates = CertificateUtils.getCertificate("https://www.reddit.com/")
.get("https://www.reddit.com/");
try (MockedStatic<CertificateUtils> certificateUtilsMockedStatic = mockStatic(CertificateUtils.class, invocation -> {
Method method = invocation.getMethod();
if ("getRootCaFromAuthorityInfoAccessExtensionIfPresent".equals(method.getName())) {
return (List) invocation.getMock();
} else {
return invocation.callRealMethod();
}
})) {
certificateUtilsMockedStatic.when(() -> CertificateUtils.getRootCaFromAuthorityInfoAccessExtensionIfPresent(any(X509Certificate.class)))
.thenReturn(Collections.emptyList());
X509Certificate certificate = (X509Certificate) certificates.get(certificates.size() - 1);
List<X509Certificate> rootCaCertificate = CertificateUtils.getRootCaIfPossible(certificate);
assertThat(rootCaCertificate).isNotEmpty();
certificateUtilsMockedStatic.verify(() -> CertificateUtils.getRootCaFromJdkTrustedCertificates(certificate), times(1));
}
} |
if ("getRootCaFromAuthorityInfoAccessExtensionIfPresent".equals(method.getName())) {
return invocation.getMock();
} else {
return invocation.callRealMethod();
}
|
@Hakky54 , could you try to replace your code with: if ("getRootCaFromAuthorityInfoAccessExtensionIfPresent".equals(method.getName())) {
return Collections.emptyList();
} The test passes with that change for me. |
Yes @temp-droid I can confirm that it is working like that. I have rewritten the test like this and it passes: @Test
void getRootCaIfPossibleReturnsJdkTrustedCaCertificateWhenNoAuthorityInfoAccessExtensionIsPresent() {
List<Certificate> certificates = CertificateUtils.getCertificate("https://www.reddit.com/")
.get("https://www.reddit.com/");
try (MockedStatic<CertificateUtils> certificateUtilsMockedStatic = mockStatic(CertificateUtils.class, invocation -> {
Method method = invocation.getMethod();
if ("getRootCaFromAuthorityInfoAccessExtensionIfPresent".equals(method.getName())) {
return Collections.emptyList();
} else {
return invocation.callRealMethod();
}
})) {
X509Certificate certificate = (X509Certificate) certificates.get(certificates.size() - 1);
List<X509Certificate> rootCaCertificate = CertificateUtils.getRootCaIfPossible(certificate);
assertThat(rootCaCertificate).isNotEmpty();
certificateUtilsMockedStatic.verify(() -> CertificateUtils.getRootCaFromJdkTrustedCertificates(certificate), times(1));
}
} This method resolves most of the issues I had. So basically what I wonder is should I rewrite my tests or do you think it is a bug and I should wait for a new mockito version? I have the feeling it Looking at the PR of #2506 it gives me the idea that I was incorrectly using mockstatic and therefor with the latest version I am getting an exception right? |
Hey @Hakky54 ,
It looks to me your implementation was wrong (because you don't return a And because you mock it again after ( In the end, you could use: try (MockedStatic<CertificateUtils> certificateUtilsMockedStatic = mockStatic(CertificateUtils.class, invocation -> {
Method method = invocation.getMethod();
if ("getRootCaFromAuthorityInfoAccessExtensionIfPresent".equals(method.getName())) {
return Collections.emptyList();
} else {
return invocation.callRealMethod();
}
})) {
X509Certificate certificate = (X509Certificate) certificates.get(certificates.size() - 1); |
Thank you for taking your time to look at this issue, and yes I totally agree with you that my test setup was not correct and adjusting it from my side fixes all the failing tests. I think we can close this issue as it is not an issue |
Hello, recently I tried to upgrade to the latest Mockito version from 4.1.0 to 4.2.0 which resulted in a failing build. I noticed that the unit tests which used mockstatic was not passing anymore. I can share a simple code snippet which worked and does not work anymore with the latest version:
FooUtils
Unit Test
The test fails and I am getting the following error:
See also this project where I use mockstatic: https://github.com/Hakky54/sslcontext-kickstart
The master branch is with mockito 4.1.0 which passes however this pull request where the latest version is being used fails: Hakky54/sslcontext-kickstart#135
I am using Java 8, 11 and 17 and it fails on all of them. I am using mockito-junit-jupiter. Any idea what could be the cause? Do you think I am using the mockstatic wrong or do I need additional configuration for the latest version?
Looking forward to hear from you guys soon.
Hakan,
The text was updated successfully, but these errors were encountered: