I have defined an Aspect and it will be used when the method is annotated. Please see the sample code below
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PredefinedCheck {
}
@Aspect
@Component
public class PredefinedAspect {
@Before("@annotation(PredefinedCheck)")
@SneakyThrows
public void check(JoinPoint joinPoint) {
......
log.debug("hello!!");
}
}
@Service
public class ActionService {
@PredefinedCheck
public MyEntity updateMyEntity(AuthenticationJwtToken authToken, EntityUpdateRequest request) {
......
}
}
Now, the question is how can I unit test my PredefinedAspect code? I thought unit testing the updateMyEntity
method will trigger it, but it didn't (I debugged and it not hit the break point. Also, the sonarqube doesn't shows the code being covered). Please advise.
Steps
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackageClasses = { PredefinedAspect.class } )
public class ApplicationTest {
public void main(String args[]) {
SpringBootApplication.run(ApplicationTest.class, args);
}
}
@SpringBootTest(classes = ApplicationTest.class)
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class
})
Full example:
import org.aspectj.lang.JoinPoint;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.stereotype.Service;
import org.springframework.test.context.junit4.SpringRunner;
import javax.sql.DataSource;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@Service
class ActionServiceFake {
@PredefinedCheck
public MyEntity updateMyEntity(AuthenticationJwtToken authToken, EntityUpdateRequest request) {
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApplicationTest.class)
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class
})
public class PredefinedAspectTest {
@SpyBean
PredefinedAspect predefinedAspect;
@Autowired
ActionServiceFake actionServiceFake;
@Test
public void shouldCheckOneTimesBefore() {
// exercise ...
actionServiceFake.updateMyEntity(new AuthenticationJwtToken(), new EntityUpdateRequest());
// expectation ...
verify(predefinedAspect, times(1)).check(any(JoinPoint.class));
}
}
You can use the external ActionService class, but, don't forget add it Application Context base classes list.