Junit 测试在作为类/包单独运行时运行良好,但在从文件夹与其他包一起运行时失败

Abi*_*ami 5 junit mockito

我在为其编写测试的文件夹下有多个包。当作为类或从驻留包运行时,这些测试会通过。但是当我从整个文件夹运行它时,测试失败并出现mockito异常。例如,EmailHandlerTest 类单独通过,并且当作为“电子邮件”包中的包运行时也通过。但是,当我从 bff 文件夹中作为一个整体运行测试时,许多类都会抛出与mockito有关的错误。

文件夹结构

从电子邮件包运行时测试通过

当从整个文件夹一起运行时,测试因mockito错误而失败

错误:

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)
Run Code Online (Sandbox Code Playgroud)

EmailHandlerTest 类中单个方法的代码。此类中还有许多其他类似的方法,但都因相同的错误而失败:

@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", "testFrom@test.com");
    ReflectionTestUtils.setField(emailHandler, "sharedMailBoxEmail", "testMailbox@test.com");
    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());
}
Run Code Online (Sandbox Code Playgroud)

Bab*_*One 5

我在最近的一个项目中遇到了类似的问题。您似乎没有在 EmailHandlerTest 中完整地提供模拟,这使得查明确切的问题变得困难。据我所知,问题在于您无法模拟 java.lang.* 中的类,因为 Mockito 依赖于它们。

正如TimvdLippe建议的那样:

不支持 java.lang.* 中的模拟类,因为 Mockito 本身基于这些类。

另外,不要嘲笑“Method”类,正如raphw建议的那样:

模拟 Method 类肯定是一个问题。Mockito(或 Byte Buddy)内部使用的模拟类会改变 Mockito(或 Byte Buddy)的行为并导致错误。

您可以在此处查看GitHub 对话以了解更多详细信息。

我希望这有帮助!