Junit 5, Spring Application Context does not close on #DirtiesContext - java

My application context is not closed after test method.
I use Junit 5.3.1, spring 5.1.0.RELEASE for Selenium WebDriver tests.
This is my bean:
#Configuration
public class WebDriverConfig {
// ... Some Code ...
#Bean(destroyMethod = "quit")
#Primary
public DelegatingWebDriver cleanWebDriver(WebDriver driver) throws Exception {
driver.manage().deleteAllCookies();
driver.manage().window().maximize();
return new DelegatingWebDriver(driver);
}
// ... Some more code ...
}
This is my class:
#ExtendWith({SpringExtension.class})
#ContextConfiguration(classes = { WebDriverConfig.class, LoggerConfig.class, EmailConfig.class})
#TestExecutionListeners(listeners= {ScreenshotTaker.class, DependencyInjectionTestExecutionListener.class, TestListener.class})
#DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class BasicScenariosIT {
#Inject
private DelegatingWebDriver driver;
#SuppressWarnings("unused")
#Inject
private URI baseUrl;
#Inject
private Logger logger;
private DelegatingExtentTest testCase;
// ... Some tests ...
}
I expect the line:
#DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
to close the application context and fire up the line:
#Bean(destroyMethod = "quit")
In my case, call method "quit" close the browser and start a new one. However it doesn't seem to happen.
Would appreciate the help

Well, I found a workaround.
I implemented spring test listeners, and in the listener I marked the context as dirty, instead of relying on the #DirtiesContext annotation.
The listener looks like this:
#ExtendWith({SpringExtension.class})
#ContextConfiguration(classes = { WebDriverConfig.class, LoggerConfig.class})
#TestExecutionListeners(listeners= {DependencyInjectionTestExecutionListener.class})
public class RunnerExtension extends AbstractTestExecutionListener {
#Autowired
protected Logger logger;
#Autowired
protected DelegatingWebDriver driver;
#Override
public void beforeTestClass(TestContext testContext) throws Exception {
testContext.getApplicationContext()
.getAutowireCapableBeanFactory()
.autowireBean(this);
}
#Override
public void beforeTestMethod(TestContext testContext) throws Exception {
// .. some code here ..
}
#Override
public void beforeTestExecution(TestContext testContext) throws Exception {
// .. some code here ..
}
#Override
public void afterTestExecution(TestContext testContext) throws Exception {
// .. some code here ..
}
#Override
public void afterTestMethod(TestContext testContext) throws IOException {
// .. some code here ..
testContext.markApplicationContextDirty(HierarchyMode.EXHAUSTIVE);
}
#Override
public void afterTestClass(TestContext testContext) throws IOException {
// .. some code here ..
}
}
The important code line is:
testContext.markApplicationContextDirty(HierarchyMode.EXHAUSTIVE);
It marks the context as dirty and a new context will be created in the next session.

Related

Unable to intercept the advice method in Spring AOP

I am implementing custom annotation processing using Spring AOP. I have below code.
public class CacheDemo {
private static ApplicationContext applicationContext;
public static void main(String args[])
{
applicationContext =
new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
}
}
//Application Configuration
#Configuration
#ComponentScan("Demo")
#Component
public class ApplicationConfiguration implements ApplicationContextAware {
#Autowired
TestCacheDemo testCacheDemo;
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
applicationContext = ctx;
}
#Bean
public void testCacheDemoIntialize()
{
testCacheDemo.setApplicationContext(applicationContext);
testCacheDemo.test();
}
}
//CustomAnnotation processor
#Aspect
#Component
public class CustomAnnotationAspect {
#Autowired
private AbstractCacheService cacheService;
#Around("#annotation(Demo.CustomCacheable)")
public Object customCacheable(ProceedingJoinPoint joinPoint) throws Throwable { // This method is not called at all
joinPoint.proceed();
// Some other code to follow
}
// Custom Annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface CustomCacheable {
}
// Annotation user
#Component
public class CacheProvider
{
#Autowired
AbstractCacheService abstractCacheService;
CacheManager<String,String> cacheManager;
#PostConstruct
void init()
{
cacheManager = CreateCache.create(s -> {return s.toUpperCase();});
abstractCacheService.setCacheManager(cacheManager);
}
#CustomCacheable
String getCacheValue(String s)
{
String str=s.toUpperCase();
return str;
}
}
For testing purpose I have created the below bean
#Component
public class TestCacheDemo extends TimerTask
{
private ApplicationContext applicationContext;
private Timer timer;
#Autowired
CacheProvider cacheProvider;
void test()
{
System.out.println("Called test");
for (String beanName : applicationContext.getBeanDefinitionNames()) {
System.out.println(beanName);
}
//CacheProvider cacheProvider = applicationContext.getBean(CacheProvider.class);
//cacheProvider.getCacheValue("Hello");
timer = new Timer();
timer.schedule(this,1000,3000);
}
void setApplicationContext(ApplicationContext ctx)
{
applicationContext=ctx;
}
#Override
public void run() {
cacheProvider.getCacheValue("Hi");
}
}
Whenever the application is started it will call the test method of the TestCacheDemo Class and sets the timer to be fired after 3 secs so that I can call the annotated method getCacheValue from inside the run method of the timer task. But when the annotated method is called the annotation processor is not invoked. Hence I am unable to do annotation processing. Please let me know where is the problem?
To use AspectJ in spring boot you must enable it.
You should add the following annotation to your application main class (CacheDemo) or application configuration class.
#EnableAspectJAutoProxy

Mock CDI Injected class using Mockito on a JUnit test

This is the method that i am trying to test:
#Singleton
public class PriorityJobQueueService {
public void registerIndividualJob(String jobCode) throws InterruptedException {
List<PriorityJobMapDTO> priorityJobMapDTOS = CDI.current().select(JobGroupsMasterService.class).get().getJobForCronScheduler(jobCode);
priorityJobMapDTOS = validateStrictJobs(priorityJobMapDTOS);
triggerJob(priorityJobMapDTOS);
}
}
This is the skeleton structure of my test file:
#RunWith(MockitoJUnitRunner.class)
public class PriorityJobQueueServiceTest {
#Before
public void beforeTest() throws Exception {
fixture = new Fixture();
}
#Test
public void registerIndividualJob_SUCCESS() throws InterruptedException {
}
private class Fixture {
#InjectMocks
PriorityJobQueueService priorityJobQueueService;
private Fixture() throws Exception {
MockitoAnnotations.initMocks(this);
}
}
}
Now, what i need to do is mock CDI.current.select() statement so that i can run the test.
The only things i've found so far is having to add additional dependencies to my project with the following libraries:
Quarkus
cdi-unit
So are there any other ways to achieve this?
I would change the code to be composable. That's the entire point of Dependency Injection :)
#Singleton
public class PriorityJobQueueService {
#Inject
private JobGroupsMasterService jobGroupsMasterService;
public void registerIndividualJob(String jobCode) throws InterruptedException {
List<PriorityJobMapDTO> priorityJobMapDTOS = jobGroupsMasterService.getJobForCronScheduler(jobCode);
priorityJobMapDTOS = validateStrictJobs(priorityJobMapDTOS);
triggerJob(priorityJobMapDTOS);
}
}
Now your test will look like
#RunWith(MockitoJUnitRunner.class)
class PriorityJobQueueServiceTest {
#Mock
private JobGroupsMasterService jobGroupsMasterService;
#InjectMocks
private PriorityJobQueueService priorityJobQueueService;
#Test
void registerIndividualJob_SUCCESS() throws InterruptedException {
priorityJobQueueService.registerIndividualJob(...);
}
}
cheers, good luck!

Apache camel Junit mock issue

I am writing a JUnit test case for a Route class. I'm facing a problem while mocking ServiceClass inside the Processor class.
public class SaveRouteTest extends CamelTestSupport {
private Exchange exchange;
protected ProducerTemplate template;
private SaveRequestBuilder saveRequestBuilder;
private SaveRoute route;
private SaveProcessor saveProcessor;
private ApplicationContext springContext = createApplicationContext();
#Mock
SaveServiceClient saveServiceClient;//Not able to mock this class
#BeforeClass
public void prepareTestCamelContext() throws Exception {
route = springContext.getBean("saveRoute", saveRoute.class);
saveProcessor = springContext.getBean("saveProcessor",
SaveProcessor.class);
saveRequestBuilder = springContext.getBean("saveRequestBuilder",
SaveRequestBuilder.class);
}
#BeforeMethod
public void init() throws SQLException, ServiceException {
MockitoAnnotations.initMocks(this);
exchange = new DefaultExchange(context);
}
#Override
protected RouteBuilder[] createRouteBuilders() throws Exception {
template = context.createProducerTemplate();
return new RouteBuilder[]{route};
}
#Test
public void testHotelCommitTransactionRouteSuccessReturn() throws
Exception {
when(saveServiceClient.invokeServiceWithName(anyObject()).
thenReturn("Response");
exchange.getIn().setBody("Request detail");
exchange = template.send("direct:SaveRoute",exchange);
}
protected ApplicationContext createApplicationContext() {
return new ClassPathXmlApplicationContext("classpath*:config/spring/testContext.xml");
}
}
#Component
public class SaveRoute extends SPRouteBuilder {
#Autowired
private SaveProcessor saveProcessor;
#Override
public void configure() throws Exception {
from("direct:SaveRoute")
.routeId("save")
.to("direct:ProcessSaveFlow")
.end();
from("direct:ProcessSaveFlow")
.process(saveProcessor)
.end();
}
}
public class SaveProcessor implements Processor {
#Autowired
SaveServiceClient saveServiceClient;
#Override
public void process(Exchange exchange) throws Exception {
//This line of code not able to mock
String response = saveServiceClient.invokeServiceWithName(exchange);
exchange.getIn().setBody(response);
}
}
How to resolve mocking of saveServiceClient.invokeServiceWithName? The debugger is always going inside this method. I tried using both mock objects and an injected mock. I can't make the method call directly.
You are creating a mock object, however you are not injecting it anywhere (normally you are doing it with #InjectMocks annotation - read about it).
I think there are several possibilities:
Provide a #MockBean object, which will be considered as a bean candidate in context.
There is a code example for mocking beans.
#RunWith ( CamelSpringRunner.class )
#SpringBootTest
public class RouteBuilderTest extends CamelSpringTestSupport {
#Autowired
private ApplicationContext applicationContext;
#MockBean
private ServiceClient serviceClient;
#Override
public void setUp() throws Exception {
MockitoAnnotations.initMocks( this );
super.setUp();
}
#Override
public void tearDown() {
}
#Test
public void test() {
when( serviceClient.doStuff() ).thenReturn( "mockedResponse" );
}
}
Mock SaveProcessor and inject it to Route class - you shouldn't take care of ServiceClient, because you are trying to test too much. Tests for SaveProcessor should be separated, tests for route don't need this logic.

DirtiesContext not clearing ApplicationContext in Spring unit tests

I have a class called SomeBean and two tests that are configured with Stubs for different scenarios. I am using Spring Boot.
The second test is supposed to pass without Exception because there is no stubbing that I did to throw Exception.
The DirtiesContext is not working as well. If I remove the commented code in Test2.java I get the test to pass. I would like to remove the unnecessary subbing by using something similar to DirtiesContext.
I may be missing something basic. Can someone point to what I am doing incorrect.
#Service
public class SomeBeanProcessor {
#Autowired
private BeanValidator beanValidator;
public ResultBean process(SomeBean sb) throws ValidationException{
beanValidator.validateBean(sb);
//Do some processing and return ResultBean;
}
}
Test1.java
RunWith(SpringRunner.class)
#SpringBootTest(classes = {MyApp.class})
#WebAppConfiguration
#ContextConfiguration(classes=Test1.Test1Config.class) {
public class Test1 {
#Configuration
static class Test1Config {
#Bean
public BeanValidator getSomeRequestValidator() {
return new BeanValidator() {
public void validateBean(SomeBean bean) throws ValidationException {
throw new ValidationException("Validation failed");
}
};
}
}
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Autowired
private SomeBeanProcessor aBeanProcessor;
#Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
#Test
#DirtiesContext
public void doTestValidationErrors() throws ValidationException{
SomeBean sb = new SomeBean();
this.aBeanProcessor.process(sb);
Assert.fail("Should throw exception");
}
}
Test2.java
RunWith(SpringRunner.class)
#SpringBootTest(classes = {MyApp.class})
#WebAppConfiguration
#ContextConfiguration(classes=Test2.Test2Config.class) {
public class Test2 {
#Configuration
static class Test2Config {
//#Bean
//public BeanValidator getSomeRequestValidator() {
// return new BeanValidator() {
// public void validateBean(SomeBean bean) throws ValidationException { //Do nothing
// }
// };
//}
}
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Autowired
private SomeBeanProcessor aBeanProcessor;
#Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
#Test
#DirtiesContext
public void doTestSuccess() throws ValidationException{
SomeBean sb = new SomeBean();
this.aBeanProcessor.process(sb);
}
}

JerseyTest and JUnit throws NullPointerException

I have some problems with the jersey test framework. If i use the #Before and #After annotations, then the target method throws a NullPointerException.
I thought JerseyTest works with JUnit? Where is my problem?
Jersey: 2.12
JUnit: 4.11
Code that fails:
public class MyResourceTest extends JerseyTest {
#Before
public void setUp() { }
#After
public void tearDown() { }
#Override
protected Application configure() {
return new ResourceConfig(MyResource.class);
}
#Test
public void SHOULD_RETURN_BAD_REQUEST() throws IOException {
System.out.println(target("myPath"));
assertEquals(1, 1);
}
}
Result:
java.lang.NullPointerException at
org.glassfish.jersey.test.JerseyTest.target(JerseyTest.java:566) at
org.glassfish.jersey.test.JerseyTest.target(JerseyTest.java:580) at
foo.bar.MyResourceTest.SHOULD_RETURN_BAD_REQUEST(MyResourceTest.java:43)
Code that works:
public class MyResourceTest extends JerseyTest {
#Override
protected Application configure() {
return new ResourceConfig(MyResource.class);
}
#Test
public void SHOULD_RETURN_BAD_REQUEST() throws IOException {
System.out.println(target("myPath"));
assertEquals(1, 1);
}
}
Result:
JerseyWebTarget { http://localhost:9998/myPath }
Your methods seem to override some important initialization made in parent JerseyTest.
Try to name them differently. E.g.:
#Before
public void setUpChild() { }
#After
public void tearDownChild() { }
I came here because I was using JUnit 5 and it seems that it wasn't seeing the #Before and #After annotations on the JerseyTest setup/tearDown methods. I had to override them and use the new JUnit 5 annotations
public class MyResourceTest extends JerseyTest {
#BeforeEach
#Override
public void setUp() throws Exception {
super.setUp();
}
#AfterEach
#Override
public void tearDown() throws Exception {
super.tearDown();
}
#Override
protected Application configure() {
return new ResourceConfig(MyResource.class);
}
#Test
public void SHOULD_RETURN_BAD_REQUEST() throws IOException {
System.out.println(target("myPath"));
assertEquals(1, 1);
}
}

Categories