Reputation: 2873
I'm writing an integration test for this Spring Boot @Service
bean
import org.springframework.stereotype.Service;
import org.thymeleaf.ITemplateEngine;
import org.thymeleaf.context.Context;
import java.util.Locale;
import java.util.Map;
@Service
public class ThymeLeafEmailTemplateService implements EmailTemplateService {
private final ITemplateEngine springTemplateEngine;
public ThymeLeafEmailTemplateService(ITemplateEngine springTemplateEngine) {
this.springTemplateEngine = springTemplateEngine;
}
public String generateEmailBody(String template, Map<String, Object> variables) {
Context context = new Context(Locale.getDefault(), variables);
return springTemplateEngine.process(template, context);
}
}
Currently, the test class is defined as shown below
@SpringBootTest
class ThymeLeafEmailTemplateServiceTests {
@Autowired
private EmailTemplateService service;
@Test
void generateTaskNotificationEmail() {
var output = service.generateEmailBody("/template", Map.of());
assertEquals("Expected Output", output);
}
}
A problem with this approach is that it's very slow/inefficient because the entire application context is loaded, but I really only need the service being tested and its dependencies.
If I change the test class' annotations to
@SpringBootTest
@ContextConfiguration(classes = ThymeLeafEmailTemplateService.class)
the test fails, because the dependency ITemplateEngine springTemplateEngine
does not exist. I could add this dependency to classes
(the list of beans to create), but this seems like a very brittle approach.
Is there an efficient way to integration test a single @Service
?
I know I could mock ITemplateEngine springTemplateEngine
and write a unit test instead, but I want to test the template's actual output, so this approach won't work
Upvotes: 1
Views: 888
Reputation: 1481
I had the exact requirement and solved it with the following config.
In my test case just call the components that are needed for the execution of the process, in this case, my service (CreaFormatoContrareciboServiceImpl) and the repository inside the service (ContrareciboRepository) and also a customized configuration for the database (RepositoryConfiguration) this is because the configuratión generated by jhipster it is not working correctly. found this here https://tanzu.vmware.com/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ContrareciboRepository.class, CreaFormatoContrareciboServiceImpl.class, RepositoryConfiguration.class})
class CreaFormatoContrareciboServiceTest {
@Autowired
private CreaFormatoContrareciboService creaFormatoContrareciboService;
@Test
void whenCodeIsFound() throws JRException {
String codigo = "DEMO";
JasperPrint jasperPrint = this.creaFormatoContrareciboService.obtener(codigo);
assertNotNull(jasperPrint);
}
}
Upvotes: 0
Reputation: 101
You can use
@WebMvcTest(ThymeLeafEmailTemplateService.class)
This will load only that bean in your application context along with any default Spring configuration beans.
Upvotes: 2