Junit Tests are running fine when run individually as Class/package, but failing when run together from folder with other packages
Asked Answered
G

4

6

I have multiple packages under a folder for which tests were written. These tests pass when run as a Class or from the residing package. But when I run it from the folder as a whole, the tests are failing with mockito exception. For example, EmailHandlerTest class passes individually and also when run as a package from "email" package. But, when I run the tests as a whole from bff folder, many of the classes are throwing error with respect to mockito.

Folder structure

Tests pass when ran from email package

Tests failing with mockito errors when run together from the folder as a whole

Error:

java.lang.NullPointerException: Cannot invoke "[Ljava.lang.Class;.clone()" because " 
<local2>.parameterTypes" is null

at java.base/java.lang.reflect.Method.getParameterTypes(Method.java:314)
at org.mockito.internal.creation.DelegatingMethod.<init>(DelegatingMethod.java:20)
at org.mockito.internal.invocation.DefaultInvocationFactory.createMockitoMethod(DefaultInvocationFactory.java:81)
at org.mockito.internal.invocation.DefaultInvocationFactory.createInvocation(DefaultInvocationFactory.java:60)
at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:83)
at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:56)
at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptAbstract(MockMethodInterceptor.java:161)
at com.<package>.bff.repository.EmailTemplateRepository$MockitoMock$520687419.findByEmailTemplateId(Unknown Source)
at <package>.bff.email.EmailHandlerTest.sendProjectCompletionMail_Should_Send_Email_Successfully(EmailHandlerTest.java:926)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)

Code of a single method in EmailHandlerTest class. There are many other similar methods in this class which are failing with the same error:

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class EmailHandlerTest {

@Mock private EmailTemplateRepository emailTemplateRepository;

<<Few Other Mocks here>>

@InjectMocks EmailHandler emailHandler;

@TempDir
Path reportDir;

private static TestUtils testUtils = new TestUtils();

List<EmailTemplate> emailTemplates;

void setup() throws IOException {
    ReflectionTestUtils.setField(emailHandler, "apiEndpoint", "testEndpoint");
    ReflectionTestUtils.setField(emailHandler, "emailIsProdEnv", false);
    ReflectionTestUtils.setField(emailHandler, "fromAddress", "[email protected]");
    ReflectionTestUtils.setField(emailHandler, "sharedMailBoxEmail", "[email protected]");
    ClassLoader classLoader = getClass().getClassLoader();
    ObjectMapper mapper = new ObjectMapper();
    InputStream inputStream= classLoader.getResourceAsStream("emailTemplates.json");
    emailTemplates = mapper.readValue(inputStream, new TypeReference<List<EmailTemplate>>(){});
}
 @Test
void sendProjectCompletionMail_Should_Send_Email_Successfully() throws IOException, ParseException {
    // Given
    setup();
    ReflectionTestUtils.setField(emailHandler, "sendProjectCompletionMailToggle", true);
    ClassLoader classLoader = getClass().getClassLoader();
    File report = new File(classLoader.getResource("Report.xlsx").getFile());
    Project project = Instancio.of(testUtils.getProjectModel()).create();
    project.setProductType(Constants.PRODUCT_TYPE_1);
    ProjectDomain projectDomain = Instancio.of(ProjectDomain.class).create();
    User assignee = Instancio.of(User.class).create();
    when(userRepository.findByUsername(any())).thenReturn(assignee);
    EmailTemplate emailTemplate = emailTemplates.stream().filter(e -> StringUtils.equalsIgnoreCase(e.getEmailTemplateId(), "TEMPLATE_ID_1")).findFirst().get();
    when(emailTemplateRepository.findByEmailTemplateId("TEMPLATE_ID_1")).thenReturn(emailTemplate);
    doNothing().when(sesEmailService).sendMail(any(), any(), any(), any(), any(), any(), any());
    Email email = Instancio.of(Email.class).create();
    when(emailRepository.save(any())).thenReturn(email);
    // When
    emailHandler.sendProjectCompletionMail(report, project, projectDomain);
    // Then
    verify(sesEmailService).sendMail(any(), any(), any(), any(), any(), any(), any());
}
Goldshlag answered 9/10, 2023 at 14:12 Comment(0)
D
7

I encountered a similar issue in one of my recent projects. It seems that you haven't provided your mocks completely in your EmailHandlerTest, making it challenging to pinpoint the exact problem. As far as I know, the problem lies in the fact that you can't mock classes from java.lang.* because Mockito relies on them.

As suggested by TimvdLippe:

Mocking classes in java.lang.* is unsupported, as Mockito itself is based on these classes.

Also, don't mock the "Method" class, as raphw suggests:

Mocking the Method class is certainly an issue. Mocking classes that Mockito (or Byte Buddy) uses internally will change the behavior of Mockito (or Byte Buddy) and lead to errors.

You can see the GitHub conversation here for more details.

I hope this helps!

Decelerate answered 17/10, 2023 at 23:13 Comment(0)
B
2

Bumped Mockito to org.mockito::mockito-core::5.10.0, that resolved the issue for me.

Booby answered 29/2 at 10:55 Comment(0)
S
0

Created an account just for you :)

I had the same issue and found a work-around very easy to implement.

Issue: Mockito doesnt like to mock interfaces (it seems) I see your error is on the repository so probably something spring-boot related interface stuff.

Solution: create an abstract class implemented the interface for the test

Here is an example for my issue doing a filter, all request, response and filter are interfaces and failed randomly depending it was all tests at once or just that test running alone. Now it's working 100%.

Before:

final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        when(request.getHeader(any())).thenReturn("foo");
        final HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        final FilterChain chain = Mockito.mock(FilterChain.class);
        filter.doFilterInternal(request, response, chain);

After:

final HttpServletRequest request = Mockito.mock(MockHttpServletRequest.class);
    when(request.getHeader(any())).thenReturn("foo");
    final HttpServletResponse response = Mockito.mock(MockHttpServletResponse.class);
    final FilterChain chain = Mockito.mock(MockFilterChain.class);
    filter.doFilterInternal(request, response, chain);
    ...
    private static abstract class MockHttpServletRequest implements HttpServletRequest {}
    private static abstract class MockHttpServletResponse implements HttpServletResponse {}
    private static abstract class MockFilterChain implements FilterChain {}
Sawfly answered 8/1 at 21:28 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Settling
P
0

I came across this exact issue as well, when trying to test some Annotations I had made. The short of it is that it was fine to mock ProceedingJoinPoint and MethodSignature, as they are interfaces, but mocking the concrete class Method is not supported. Thankfully, the object itself is easy to construct.

Praise answered 26/8 at 23:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.