mockito 无法嘲笑Logger

ccrfmcuu  于 9个月前  发布在  其他
关注(0)|答案(2)|浏览(150)

我试图模拟@Slf4j为我的一个单元测试提供的记录器。但是我无法做到这一点。
下面是我使用的代码示例。
我的服务代码

package com.someorg;

import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import java.util.Set;

@Service
@RequiredArgsConstructor
@Slf4j
public class EmailNotificationService implements NotificationService {

    private final JavaMailSender javaMailSender;

    @Value("${spring.mail.from}")
    private String from;

    public void send(String content, String subject, Set<String> receivers){
        // Sends HTML email to Set of receivers
        MimeMessage message = javaMailSender.createMimeMessage();
        try{
            MimeMessageHelper messageHelper = new MimeMessageHelper(message,true);
            messageHelper.setSubject(subject);
            messageHelper.setText(content,true);
            messageHelper.setTo(receivers.toArray(new String[0]));
            messageHelper.setFrom(from);
            javaMailSender.send(message);
        }catch(MessagingException | RuntimeException e){
            log.warn("Error while sending email notification with subject %s".formatted(subject),e);
        }
    }
}

字符串
我的测试文件

package com.someorg;

import jakarta.mail.internet.MimeMessage;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mail.MailSendException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.test.context.TestPropertySource;

import java.util.Collections;
import java.util.Set;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@SpringBootTest(classes = {EmailNotificationService.class})
@TestPropertySource(properties = {"[email protected]"})
class EmailNotificationServiceTest {

    @MockBean
    private JavaMailSender javaMailSender;
    @Mock
    private MimeMessage mimeMessage;
    @Mock
    Logger logger;
    @Autowired
    private EmailNotificationService emailNotificationService;
    private static final String CONTENT = "Test content";
    private static final String SUBJECT = "Test subject";
    private static final Set<String> RECEIVERS = Collections.singleton("[email protected]");

  
    @Test
    void testSendWithException(){
        // Arrange
        when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage);
        doThrow(new MailSendException("Simulated exception")).when(javaMailSender).send(mimeMessage);
        // Act
        emailNotificationService.send(CONTENT, SUBJECT, RECEIVERS);
        // Assert
        verify(javaMailSender).send(any(MimeMessage.class));
        verify(logger).warn(any(String.class), any(MailSendException.class));
    }
}


我的电子邮件通知服务没有模拟测试文件中Logger提供的记录器。我得到的错误是enter image description here
我尝试了不同的东西,删除@Autowired和其他不同的东西,但它不工作。

voj3qocg

voj3qocg1#

也许你可以试试Captor,比如:

@Captor
protected ArgumentCaptor<Logger> logger;

字符串
另外,要Assert正在抛出错误,也许可以执行以下操作:

Assertions.assertThrows(MailSendException.class, () -> emailNotificationService.send(CONTENT, SUBJECT, RECEIVERS));

svmlkihl

svmlkihl2#

在用Lombok@Slf4j注解的类中模拟logger可能很棘手,因为logger是在编译时生成的,在测试中不容易进行模拟。logger是类中的静态字段,这增加了模拟它的额外复杂性。
我可以尝试使用以下库:https://www.simplify4u.org/slf4j-mock/
下面是一个示例:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Example {

    private static final Logger LOGGER = LoggerFactory.getLogger(Example.class);

    public void methodWithLogInfo(String message) {
        LOGGER.info(message);
    }
}

字符串
如果您使用的是Junit 5,则可以执行以下操作:

@ExtendWith(MockitoExtension.class)
class JUnit5ExampleTest {

    private static final String INFO_TEST_MESSAGE = "info log test message from JUnit5";

    @Mock
    Logger logger;

    @InjectMocks
    Example sut;

    @Test
    void logInfoShouldBeLogged() {

        // when
        sut.methodWithLogInfo(INFO_TEST_MESSAGE);

        // then
        Mockito.verify(logger).info(INFO_TEST_MESSAGE);
        Mockito.verifyNoMoreInteractions(logger);
    }

}


您可以在文档中找到所有示例。
另一个选择是创建一个自定义的appender,将日志保存在内存中。

相关问题