Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@SpringBootTest does not autowire JavaMailSender and throws error

What am I doing wrong here? My understanding is Spring should autowire JavaMailSender the way its autowiring EventRepository. Any guidance?

application.properties and application-test.properties

mail.host='smtp.gmail.com' -
mail.port=587
mail.username=username
mail.password=password
mail.properties.mail.smtp.starttls.enable=true

My Implementation class : This works fine if I run my application

      @Service
            public class EventService {
             private EventRepository eventRepository;
             private JavaMailSender javaMailSender;

                public EventService(EventRepository eventRepository, JavaMailSender   javaMailSender) {
                    this.eventRepository = eventRepository;
                    this.javaMailSender = javaMailSender;
                }

                public Event send(Event event) {
                   SimpleMailMessage message = new SimpleMailMessage();
                    message.setText("");
                    message.setSubject("");
                    message.setTo("");
                    message.setFrom("");
                    javaMailSender.send(message);
                    return eventRepository.save(event);
                }

            }

My Integration Test class : Able to Autowired EventRepository but not JavaMailSender.

       @RunWith(SpringRunner.class)
        @SpringBootTest
        public class ApplicationIntegrationTests {
            @Autowired
            private EventService eventService;

         @Test
            public void test() throws Exception {
                eventService.save(new Event());
        }

        }

ERROR:

Caused by: 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: {}
            at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
like image 266
T D Avatar asked Mar 05 '17 14:03

T D


3 Answers

Please make sure that your test reside in the same package as your main @SpringBootApplication class.

for example if @SpringBootApplication class is in src/main/java/some/package then your @SpringBootTest need to be in src/test/java/some/package. If it is not, you need to explicitly set @ComponentScan to include some.package. You can also use @SpringBootTest(classes=...), @ContextConfiguration(classes=...)}.

You can also put a @SpringBootConfiguration class in your test package that scans for your main package.

like image 196
Tom Avatar answered Nov 07 '22 04:11

Tom


In my case that was caused by difference in application.properties files in main and test resources.

Following properties were missing in test file:

spring.mail.host=<my host>
spring.mail.port=<my port>
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000

Please note that it is not best idea to use external services in unit tests.

like image 2
igor Avatar answered Nov 07 '22 05:11

igor


You should define one of the properties spring.mail.host or spring.mail.jndi-name for spring autoconfiguration or define your own bean in your config class.

Check this class org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration for details.

Example:

@Service
public class MyEmailService {

    @Autowired
    private JavaMailSender mailSender;

}
import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration;

@RunWith(SpringRunner.class)
@SpringBootTest(
   properties = "spring.mail.host=localhost", // <--- inlined property
   classes = {MyEmailService.class, MailSenderAutoConfiguration.class}
)
public class MyEmailServiceTest {

    @Autowired
    private MyEmailServiceTest emailService;

    @Autowire 
    private JavaMailSender javaMailSender; // if you need

    @Test
    public void validEmails() {
        // some tests of emailService
    }
}
like image 2
Sergey Nemchinov Avatar answered Nov 07 '22 03:11

Sergey Nemchinov