Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring unit test results in NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.mail.javamail.JavaMailSender'

I have this REST controller:

package com.company.rest;

@RestController
@RequestMapping("/v1/orders")
public class OrderController {

    @Autowired
    private OrderService orderService;
...

being the OrderService implementation:

package com.company.service.impl;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private MessageService messageService;
...

and MessageService implementation:

package com.company.service.impl;

import org.springframework.mail.javamail.JavaMailSender;

@Service
public class MessageServiceImpl implements MessageService {

    @Autowired
    public JavaMailSender emailSender;
...

This works perfect in development environment, but I have this unit test for the OrderController (based on this tutorial):

package com.company.test;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = AdminApplication.class)
@WebAppConfiguration
public class OrderTest {

    private MockMvc mockMvc;

    @Autowired
    private OrderService orderService;
...

which results in:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.mail.javamail.JavaMailSender' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Why does this dependency is satisfied in production but not in test? What do I need to do to allow this unit test successfully inject (or mock) a JavaMailSender implementation?

like image 955
y.luis Avatar asked Mar 08 '23 13:03

y.luis


1 Answers

The JavaMailSender bean is not created beacause Spring test runner cannot get required configuration. For example, there is no spring.mail.host in application.properties.

One of the solution is adding a TestConfiguration for JavaMailSender.

@TestConfiguration
public class TestConfigForMail {

  @Bean
  public JavaMailSender mailSender() {
    final JavaMailSenderImpl sender = new MockMailSender();
    return sender;
  }

  private class MockMailSender extends JavaMailSenderImpl {
    @Override
    public void send(final MimeMessagePreparator mimeMessagePreparator) throws MailException {
      final MimeMessage mimeMessage = createMimeMessage();
      try {
        mimeMessagePreparator.prepare(mimeMessage);
        final String content = (String) mimeMessage.getContent();
        final Properties javaMailProperties = getJavaMailProperties();
        javaMailProperties.setProperty("mailContent", content);
      } catch (final Exception e) {
        throw new MailPreparationException(e);
      }
    }
  }
}

Note: The code of MockMailSender is came from Fahd Shariff.

Then import the TestConfiguration to your test case.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = AdminApplication.class)
@Import(TestConfigForMail.class)
@WebAppConfiguration
public class OrderTest {

    private MockMvc mockMvc;

    @Autowired
    private OrderService orderService;
...
like image 164
Beck Yang Avatar answered Mar 10 '23 05:03

Beck Yang