1

I am sending an email with a thymeleaf template engine. When I didnt use thymeleaf, the mail Unit tests were running perfectly, but after I added thymeleaf the tests keep giving me NullPointerException. Here is my code from the EmailService:

 private JavaMailSender javaMailSender;
    private TemplateEngine templateEngine;

    public EmailServiceImpl(JavaMailSender javaMailSender, TemplateEngine templateEngine){
        this.javaMailSender = javaMailSender;
        this.templateEngine = templateEngine;
    }

    @Override
    public void sendEmail(Employee employee,String email) throws MessagingException {
        Context context = new Context();
        context.setVariable("employee",employee);

        String process = templateEngine.process("/email",context);

        MimeMessage message = javaMailSender.createMimeMessage();
        MimeMessageHelper helper;
        helper = new MimeMessageHelper(message, true);
        helper.setTo(email);
        helper.setSubject("Hello "+employee.getName());
        helper.setText(process,true);
        javaMailSender.send(message);

    }

and here is my test:

  @Autowired
     TemplateEngine templateEngine;


    static Context context;

    @Mock
    private JavaMailSender javaMailSender;


    @InjectMocks
    private EmailServiceImpl emailServiceImpl;

    private MimeMessage mimeMessage;
    private MimeMessageHelper helper;
    private String email;

    Employee employee;
    String process;



    @BeforeEach
    public void setUp() throws MessagingException {


        employee = new Employee("John Smith",
                20.0,"AB243", "A","B",
                LocalDateTime.now().plusDays(2),20);
       
        mimeMessage = new MimeMessage((Session)null);
      
        email = "someone@gmail.com";
        context = new Context();
        process = templateEngine.process("/email",context);
        helper.setText(process,true);



    }

    @Test
   public void emailTest() throws MessagingException {
       when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage);
       String recipient = email;
        emailServiceImpl.sendEmail(employee,email);
        assertEquals(recipient, mimeMessage.getRecipients(MimeMessage.RecipientType.TO)[0].toString());
    }

So I tried autowiring the template engine, I tried just initializing it, I tried setting the helper properties, but nothing worked. Does anyone know how to apporach this problem? Thank you!

2 Answers2

0

This seems to be happen since the process method is final which doesn't always work well with mockito. I see two options to come around this

  1. Create a wrapper claass a here
  2. Use the mock-maker-inline approach described here

I tried the second approach and it worked well for me when I use @Mock on the TemplateEngine, example:

@Mock private TemplateEngine templateEngine;
@Mock private JavaMailSender javaMailSender;
@InjectMocks private EmailServiceImpl emailServiceImpl;

 @Test
public void should_send_email() throws MessagingException {
// given
var employee = new Employee("John Smith");
var mimeMessage = Mockito.mock(MimeMessage.class);
given(templateEngine.process(eq("/email"), any(Context.class)))
    .willReturn("a template");
given(javaMailSender.createMimeMessage())
    .willReturn(mimeMessage);

// when
emailServiceImpl.sendEmail(employee, "test@mail.com");

// then
verify(javaMailSender, times(1)).send(mimeMessage);
}
Hans-Christian
  • 542
  • 4
  • 6
0

Simply put, TemplateEngine is null. The fact that you use @Autowired doesn't help as this only works when you have @SpringBootTest. Within a simple Junit test, @Autowired doesn't work - you should get a warning about that in intellij.

So you have to either use @SpringBootTest or instantiate TemplateEngine manually.

Manually you need this:

SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(new StaticApplicationContext());
        templateResolver.setPrefix("classpath:/templates/");
        templateResolver.setSuffix(".xml");
        templateResolver.setTemplateMode(TemplateMode.HTML);

        templateEngine = new SpringTemplateEngine();
        templateEngine.setEnableSpringELCompiler(true);
        templateEngine.setTemplateResolver(templateResolver);
        EmailRenderer renderer = new EmailRenderer(templateEngine);
ACV
  • 9,964
  • 5
  • 76
  • 81