Mocked object in a whole spring Batch test - spring

I want to test a whole Spring Batch but Ihave a problem. I have a service to delete rows in a DB and in a LDAP.
For the BD I have implemented a H2 in-memory database so no problems.
For the LDAP it's more difficult to have a in-memory LDAP so I want to fake the DAO LDapRepository calling method "delete" (LDapRepository is the interface and LDapRepositoryImpl annotated by #Repository the implementation)
So I tried to inject a mock in my configuration but it doesn't work.
The test fails with a null pointer exception when I try to make the fake call ldapRepository.removePerson (so ldapRepository is not correctly injected).
How is it possible to substitute the bean LDapRepository in my configuration ?
Here's the test code :
#ContextConfiguration(locations = {"classpath:purge/job-test.xml"})
public class PurgeJobTest {
#Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
#InjectMocks
#Qualifier(value = "ldapRepositoryImpl")
private LdapRepository ldapRepository;
#Test
public void testExampleJob() throws Exception {
Mockito.doNothing().when(ldapRepository.removePerson(any(String.class)));
JobParameters jobParameters = new JobParametersBuilder()
.addString("fichierJob", "/purge/job-test.xml")
.addString("nomJob", "purgeJob").toJobParameters();
JobExecution exec =jobLauncherTestUtils.launchJob(jobParameters);
assertEquals(BatchStatus.COMPLETED, exec.getStatus());
}
}

OK so I admit my question was a little tricky but I want to share the answer to other people who faced a similar problem.
The null pointer exception was quite logic. Indeed the bean was not recognized in the context because nowhere it was correctly injected in it.
It's a common pitfall related by example in this post Injecting Mockito Mock objects using Spring JavaConfig and #Autowired.
or this other post : Injecting Mockito mocks into a Spring bean
So in my job-test.xml I commented the component-scan in which my "real" LdapRepository" and LdapRepositoryImpl were declared and replace them with :
<bean id="ldapRepository" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="purge.batch.repository.LdapRepository" />
</bean>
<bean id="ldapRepositoryImpl" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="purge.batch.repository.LdapRepositoryImpl" />
</bean>
(I could have place these bean declaration before the component-scan to give it priority)
And that works like a charm !

Related

How can I create the spring bean after all other beans?

For example, I have 3 beans in my spring configuration: A, B, C. And I want to create bean B and C as usual. And than (when all others beans were created) I want to ask spring to create bean A.
Any suggestion ?
Thanks.
Spring framework triggers a ContextRefreshedEvent once the contexts has been fully refreshed and all the configured beans have been created.
You could try to create a listener to catch that event and initialise bean A.
#Component
public class ContextRefreshedEventListener implements
ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// Init your bean here
}
}
You should try #DependsOn adnotation
For example
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
<property name="manager" ref="manager" />
</bean>
<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
I know it's not really a bean ordering answer, but maybe you can achieve your goal with a #PostConstruct method that will be called just after a bean is constructed, dependencies are injected and all properties are set.
best nas
Easier way to do this would be using #Lazy annotation to your bean. This makes your bean do not get initialized eagerly during context initialization. In simple words,your bean will get created when you ask for it, not before.
#Bean
#Lazy
public A beanA() {
//some code here
}

How to inject mock datasource when using in Junit test

In my application,we bind the datasource through the JNDIlook up using below code:
<bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:/jboss/datasources/efmDS</value>
</property>
</bean>
Dao has code like below:
#Autowired
#Qualifier("jndiDataSource")
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
Now I am having problem while running Junit test case.
I am testing a service method which is annotated with #Transactional.
This service method internally calls some dao method which I have already mocked using mockito but I am facing issues as when transaction is getting started it tries to fetch connection from datasource which is not present and throws communicationslinkfailure exception
How can I mock datasource in this case ? or any other alternative to solve the issue is also appreciated ?

why there is no corresponding set method in this case?

I am new to Spring and working on a project which is consisting of Spring in it .
It has got this piece of code inside the xml file
<bean id="quotClient" class="com..at.client.QuoteClient" scope="singleton" />
<bean id="streamClient" class="com.at.client.StreamClient" scope="singleton" />
And inside the java class it has got this piece of code
#Autowired
#Qualifier("streamClient")
private StreamClient sclient;
#Autowired
#Qualifier("quotClient")
private QuoteClient quotesClient;
public void setQuotesClient(QuoteClient quotesClient) {
this.quotesClient = quotesClient;
}
Please let me know why there is no method by name set for the StreamClient class , but which has got corresponding set method for QuoteClient .
Since you're using annotation driven Autowiring of the beans you don't need any setters for injunction (these are set by using reflection). Even setQuotesClient isn't needed by Spring DI framework to inject those 2 bean instances.
PS: From spring version 3.0, you can start using #Inject instead of #Autowired.
Check: How does Spring #Autowired work
i think that setter method wrote by mistake.
remove that setter and test the application. it should work.

Autowiring the bean

I am new to spring and i have a question on autowiring the bean
So basically in my context file i have defined a bean called
<bean id="offerpricedao" class="com.impl.OfferPriceDAOImpl" >
<constructor-arg index="0" ref="offerpriceclass"></constructor-arg>
<constructor-arg index="1" ref="myrole"></constructor-arg>
<constructor-arg index="2"><null/></constructor-arg>
</bean>
And every other bean i have defined here which are referring ..
This code is in src main java..
and in src main test i have a testng test which loads this configuration file and in my test
i have some thing like this
#ContextConfiguration(locations = { "classpath:Context.xml" })
public class SetOfferPricesTest extends AbstractTestNGSpringContextTests {
#Autowired
IOfferPriceDAO test;
}
and this autowiring works fine ...
I thought we should have this in my configuration file for autowire work..
with out this how my autowiring is working..?
You might be having something like default-autowire="byName" in context xml. When you add #Autowired Spring finds the implementation of that interface and autowires it. In your case the implementation is com.impl.OfferPriceDAOImpl
Also the #ContextConfiguration annotation loads the context xml from the classpath
Above config and code is not enough to say how it works.
Since it Works,so the bean is defined some where in the Context.xml or in the xml files imported in context.xml.
And what dhanush said is also true.

Dynamic Dependency Injection Spring

I have following code inside my class
public void startListeners() throws Exception {
List<QueueConfiguration> queueConfigs = queueConfigResolver.getQueueConfigurations();
for(QueueConfiguration queueConfig : queueConfigs){
//TODO : work on this make it more testable
ICustomListener readerListener = new MyCustomListener(queueConfig);
readerListeners.add(readerListener);
readerListener.start();
}
}
I am using Spring for dependency injection(not in this case but overall). Now there two problems with this code.
I cannot put mock for each of the listeners created, while testing.
I dont want to use ApplicationContext.getBean() because it will have same affect. AFAIK spring cannot do this dynamically , but any other pointers?
As far as I can understand, you want to create a new bean instead of
ICustomListener readerListener = new MyCustomListener(queueConfig);
If that is the case, creating a factory for mycustomlistener and using
public abstract TestClient createTestClient();
to create your beans, and defining
<bean id="testClient" class="com.myproject.testbeans.TestClient" scope="prototype">
</bean>
<bean id="testClientFactory" class="com.myproject.testbeans.TestClientFactory">
<lookup-method name="createTestClient" bean="testClient" />
</bean>
in your context will solve your problem. This way, every time the createTestClient method of the factory is called, a new bean is created and given to your code. However, you have to give the config object via a setter instead of the constructor.

Resources