I have a @Service
to send verification emails. Here is the code of the service:
package my.package.service.impl;
//imports
@Service
public class EmailSenderServiceImpl implements EmailSenderService {
private final static Logger LOGGER = LoggerFactory.getLogger( EmailSenderServiceImpl.class );
@Autowired
EmailVerificationTokenService emailVerificationService;
@Autowired
EmailService emailService;
@Override
public boolean sendVerificationEmail( final String appUrl, final Locale locale, final UserDto user ) {
final String token = UUID.randomUUID().toString();
emailVerificationService.insertToken( user.getIdUser(), token );
final String body = createEmailBody( appUrl, locale, user, token );
final String to = user.getEmail();
final String subject = MessageResourceUtility.getMessage( "e.verify.email.subject", null, locale );
return sendEmail( body, to, subject );
}
private boolean sendEmail( final String body, final String to, final String subject ) {
try {
if( emailService.sendEmail( to, subject, body ) ) {
return true;
} else {
LOGGER.debug( "Email NOT sent" );
return false;
}
} catch( final MessagingException e ) {
LOGGER.error( "Error sending email" );
return false;
}
}
private String createEmailBody( String appUrl, final Locale locale, final UserDto user, final String token ) {
appUrl = appUrl.substring( 0, appUrl.lastIndexOf( "/" ) );
appUrl += "/accountVerification?token=" + token;
appUrl += "&username=" + user.getUserName();
final Object[] array = new Object[] { user.getName(), user.getSurname(), appUrl };
final String body = MessageResourceUtility.getMessage( "e.verify.email", array, locale );
return body;
}
}
And here is the test class:
package my.package.app.service;
//imports
@RunWith( PowerMockRunner.class )
@PrepareForTest( MessageResourceUtility.class )
public class EmailSenderServiceTest {
private static final String URL = "https://www.ysi.si/register/";
@InjectMocks
EmailSenderService emailSenderService = new EmailSenderServiceImpl();
@Mock
EmailService emailService;
@Mock
EmailVerificationTokenService emailVerificationTokenService;
Locale locale;
UserDto user;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks( this );
user = new UserDto();
when( emailService.sendEmail( Matchers.anyString(), Matchers.anyString(), Matchers.anyString() ) ).thenReturn( true );
mockStatic( MessageResourceUtility.class );
}
@Test
public void shouldCreateValidationToken() throws Exception {
emailSenderService.sendVerificationEmail( URL, locale, user );
verify( emailVerificationTokenService, times( 1 ) ).insertToken( Matchers.anyInt(), Matchers.anyString() );
}
@Test
public void shouldReturnFalseWhenError() throws Exception {
when( emailService.sendEmail( Matchers.anyString(), Matchers.anyString(), Matchers.anyString() ) ).thenThrow( new MessagingException() );
final boolean returnValue = emailSenderService.sendVerificationEmail( URL, locale, user );
assertEquals( "Returns false when error", false, returnValue );
}
@Test
public void shouldReturnFalseWhenEmailNotSent() throws Exception {
when( emailService.sendEmail( Matchers.anyString(), Matchers.anyString(), Matchers.anyString() ) ).thenReturn( false );
final boolean returnValue = emailSenderService.sendVerificationEmail( URL, locale, user );
assertEquals( "Returns false when email not sent", false, returnValue );
}
@Test
public void shouldSendAnEmailWithTheToken() throws Exception {
final boolean returnValue = emailSenderService.sendVerificationEmail( URL, locale, user );
verify( emailService, times( 1 ) ).sendEmail( Matchers.anyString(), Matchers.anyString(), Matchers.anyString() );
assertEquals( "Returns true when success", true, returnValue );
}
}
I have the feeling I am not unit testing in the proper way. I feel like the test code is too coupled to production code. Am I right?