0
@Service
@Slf4j
public class EmailService {
    @Autowired
    private final FreeMarkerConfigurationFactoryBean emailConfig;
    @Autowired
    private final HttpEmailService httpEmailService;

    public String bookingEmail(ScheduledTimeList scheduledTimeList, String appEmail) throws Exception {
            EmailRequest emailRequest = new EmailRequest();
            emailRequest.setTo(appEmail);
            emailRequest.setSubject("Subject");
            Map<String, Object> modelApp = new HashMap<>();
            modelApp.put("appEmail", appEmail);
            modelApp.put("scheduledTimeList", scheduledTimeList);

            Configuration configuration = emailConfig.getObject();
            Template template = configuration.getTemplate("emailTemplateNames.ftl");
            String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
            emailRequest.setHtmlContent(html);
            httpEmailService.sendEmail(emailRequest);
            return "success";
    }
}

Issues:

  • I want to write a test case for bookingEmail method. How can I do it using @runwith(springrunner.class)?
  • Can we do it using @runwith(mockitojunitrunner.class) also? If yes then How?
  • How can I capture the argument in test case

EmailServiceTest.java

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {EmailService.class})
public class EmailServiceTest {
    DemoBookingEntity demoBookingEntity;
    @Autowired
    @Qualifier("emailConfigBean")
    private FreeMarkerConfigurationFactoryBean emailConfig;
    @MockBean
    private HttpEmailService httpEmailService;
    @Autowired
    private EmailService emailService;

    @Before
    public void setup() {
        emailService = new EmailServiceTest(httpEmailService, emailConfig);
        demoBookingEntity = DemoBookingEntity.builder()
                .appId("appId")
                .timeSlotList(Arrays.asList(new TimeSlot("1677763200", "1677766800"), new TimeSlot("1677770400", "1677774000")))
                .demoParticipants(Arrays.asList("Participant1"))
                .build();
    }

    @Test
    public void bookADemoApiTest() throws Exception {
        ...

        ResponseEntity<String> response = emailService.bookADemoApi(demoBookingEntity, appEmail);

    }
}

TestConfig.java

@Configuration
public class TestConfig {
    @Bean(name="emailConfigBean")
    public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration(ResourceLoader resourceLoader) {
        FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
        bean.setTemplateLoaderPath("classpath:/templates/");
        return bean;
    }
}
Eshan Akash
  • 21
  • 1
  • 3
  • You don't nor should you. It is a `FactoryBean` which will create a Freemarker `Configuration` object for you to use. So don't inject the `FactoryBean`, just inject the `Configuration`. – M. Deinum Jul 11 '23 at 05:43
  • 1
    I would recommend that you rewrite your `EmailService` for constructor injection instead of field injection. This improves (not only) testability. See e.g. https://stackoverflow.com/questions/19381846/why-use-constructor-over-setter-injection-in-cdi for a more detailed explanation. – cyberbrain Jul 11 '23 at 06:05

0 Answers0