I am trying to auto-wire a spring managed bean to use in my unit test case. But autowired bean is always null. Below are my setting.
my unit test class
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration(locations = "classpath*:business-context-test.xml")
public class SMSGatewayTest {
#Autowired
#Qualifier("mySMSImpl")
private ISMSGateway smsGateway;
#Test
public void testSendTextMessage() throws Exception {
smsGateway.sendText(new TextMessage("TEST"));
// ^___________ this is null, even though I have set ContextConfiguration
}
}
spring managed bean
package com.myproject.business;
#Component("mySMSImpl")
public class MySMSImpl implements ISMSGateway {
#Override
public Boolean sendText(TextMessage textMessage ) throws VtsException {
//do something
}
}
context for unit test case
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.myproject.business"/>
</beans>
I have seen many questions and all are giving the answers that I've already incorporated in my code. Can some one tell me what I am missing. I am using intellij 14 to run my test case.
You are having code like this :
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration(locations = "classpath*:business-context-test.xml")
public class SMSGatewayTest {
..
..
}
Do you really wannna use MockitoJUnitRunner as I am not seeing any more mocks in the class.
Please try running the JUnit with like
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath*:business-context-test.xml")
public class SMSGatewayTest {
..
..
}
Edit -
#RunWith(SpringJUnit4ClassRunner.class) makes all those dependencies available which are declared using #ContextConfiguration(..) to the class on which it is used.
For example, in your case you have #RunWith(SpringJUnit4ClassRunner.class) on the class - SMSGateway. So it makes available all those dependencies to SMSGateway which are configured using #ContextConfiguration(locations = "classpath*:business-context-test.xml")
This helps to autowire 'smsGateway' inside your class SMSGateway. As you was using #RunWith(MockitoJUnitRunner.class), this dependency was not available for autowiring and hence spring was complaining. You will need MockitoJUnitRunner.class if you are using Mockito in your application. As you are not mocking any of your classes, you don't need MockitoJUnitRunner as of now.
Please take a look at - Mockito, JUnit and Spring
for more clarifications.
Take a look at http://www.alexecollins.com/tutorial-junit-rule/ . This will help you to understand how '#Runwith' and '#ContextConfiguration' annotations work behind the scenes.
There is an extra whitespace in the Bean name
#Component("mySMSImpl ")
#Qualifier("mySMSImpl")
Why would you use the Qualifier annotation in this case? Are there multiple implementations of the ISMSGateway interface?
Related
Following the question Understanding Spring #Autowired usage I wanted to create a complete knowledge base for the other option of spring wiring, the #Configuration class.
Let's assume I have a spring XML file that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<import resource="another-application-context.xml"/>
<bean id="someBean" class="stack.overflow.spring.configuration.SomeClassImpl">
<constructor-arg value="${some.interesting.property}" />
</bean>
<bean id="anotherBean" class="stack.overflow.spring.configuration.AnotherClassImpl">
<constructor-arg ref="someBean"/>
<constructor-arg ref="beanFromSomewhereElse"/>
</bean>
</beans>
How can I use #Configuration instead? Does it have any affect on the code itself?
Migrating XML to #Configuration
It is possible to migrate the xml to a #Configuration in a few steps:
Create a #Configuration annotated class:
#Configuration
public class MyApplicationContext {
}
For each <bean> tag create a method annotated with #Bean:
#Configuration
public class MyApplicationContext {
#Bean(name = "someBean")
public SomeClass getSomeClass() {
return new SomeClassImpl(someInterestingProperty); // We still need to inject someInterestingProperty
}
#Bean(name = "anotherBean")
public AnotherClass getAnotherClass() {
return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse); // We still need to inject beanFromSomewhereElse
}
}
In order to import beanFromSomewhereElse we need to import it's definition. It can be defined in an XML and the we'll use #ImportResource:
#ImportResource("another-application-context.xml")
#Configuration
public class MyApplicationContext {
...
}
If the bean is defined in another #Configuration class we can use the #Import annotation:
#Import(OtherConfiguration.class)
#Configuration
public class MyApplicationContext {
...
}
After we imported other XMLs or #Configuration classes, we can use the beans they declare in our context by declaring a private member to the #Configuration class as follows:
#Autowired
#Qualifier(value = "beanFromSomewhereElse")
private final StrangeBean beanFromSomewhereElse;
Or use it directly as parameter in the method which defines the bean that depends on this beanFromSomewhereElse using #Qualifier as follows:
#Bean(name = "anotherBean")
public AnotherClass getAnotherClass(#Qualifier (value = "beanFromSomewhereElse") final StrangeBean beanFromSomewhereElse) {
return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse);
}
Importing properties is very similar to importing bean from another xml or #Configuration class. Instead of using #Qualifier we'll use #Value with properties as follows:
#Autowired
#Value("${some.interesting.property}")
private final String someInterestingProperty;
This can be used with SpEL expressions as well.
In order to allow spring to treat such classes as beans containers we need to mark this in our main xml by putting this tag in the context:
<context:annotation-config/>
You can now import #Configuration classes exactly the same as you would create a simple bean:
<bean class="some.package.MyApplicationContext"/>
There are ways to avoid spring XMLs altogether but they are not in the scope of this answer. You can find out one of these options in my blog post on which I'm basing my answer.
The advantages and disadvantages of using this method
Basically I find this method of declaring beans much more comfortable than using XMLs due to a few advantages I see:
Typos - #Configuration classes are compiled and typos just won't allow compilations
Fail fast (compile time) - If you forget to inject a bean you'll fail on compile time and not on run-time as with XMLs
Easier to navigate in IDE - between constructors of beans to understand the dependency tree.
Possible to easily debug configuration startup
The disadvantages are not many as I see them but there are a few which I could think of:
Abuse - Code is easier to abuse than XMLs
With XMLs you can define dependencies based on classes that are not available during compile time but are provided during run-time. With #Configuration classes you must have the classes available at compile time. Usually that's not an issue, but there are cases it may be.
Bottom line: It is perfectly fine to combine XMLs, #Configuration and annotations in your application context. Spring doesn't care about the method a bean was declared with.
I have the code #Inject works in one class but not in other.
Here's my code:
context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
<context:component-scan base-package="com.myfashions.services"/>
<context:component-scan base-package="com.myfashions.dao"/>
</beans>
SellerRetriever.java
public class SellerRetriever {
#Inject
UserDAO userDAO;
...
...
}
UserDAO class is present in com.myfashions.dao package.
#Inject is not working in Seller.java. Any reason why?
Make sure that both SellerRetriever and the implementation of UserDAO are annotated for the component scan. This will ensure that the latter is injected into the former:
#Service
public class SellerRetriever {
#Inject
UserDAO userDAO;
...
}
Annotate the UserDAO implementation with #Component.
When scanning multiple paths use:
<context:component-scan base-package="com.myfashions.services, com.myfashions.dao"/>
To be eligible to scan, your class must be annotated with either a more generic #Component, or #Service or #Repositories etc.. In your case, #Service logically better fits.
You could then (if you need) define some aspects (AOP) focused specifically on services call.
Besides, you may want to use #Autowired instead of #Inject to retrieve your bean.
For more information about differences concerning these two annotations:
What is the difference between #Inject and #Autowired in Spring Framework? Which one to use under what condition?
and you can see my comment just below explaining one good reason to keep #Autowired instead of #Inject.
I found my mistake, I'm posting this because in case anyone has the same problem. I used new operator to create an SellerRetriver object. Inject won't work if new operator is used to call that particular class.
I'm trying to test a simple Aspect.
The app compiles and runs fine, BUT I do not get the Aspect executed. Or at least, I do not get the output the aspect should produce.
(my aim is to write an exception logger for any ex that occures in the app. but first this test aspect should run...)
Maybe someone who has more experience in aspects see's what I'm doing wrong?
package business;
public interface Customer {
void addCustomer();
}
import org.springframework.stereotype.Component;
#Component
public class CustomerImpl implements Customer {
public void addCustomer() {
System.out.println("addCustomer() is running ");
}
}
#RequestScoped #Named
//this is backing bean for jsf page
public class Service {
#Inject
Customer cust;
add() {
System.out.println("Service is running ");
cust.addCustomer();
}
}
#Aspect
public class AspectComp {
#Before("within(business..*)")
public void out() {
System.out.println("system out works!!");
}
}
Spring:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
<context:annotation-config />
<context:component-scan base-package="business" />
<aop:aspectj-autoproxy />
</beans>
Output:
Service is running
addCustomer() is running
The Aspect statement is missing.
You are creating your Component with its constructor, and not getting it from Spring container! That's the problem, or you must use AspectJ's load-time weaver.
Just inject your component (CustomerImpl) in your service and then use the injected instance.
I remember having a similar problem once; Spring wasn't actually loading the proxy as it did not recognize the #Aspect annotation as being an annotation-scanable bean. I added the #Component annotation to the #Aspect notation and Spring started scanning it.
I never looked into the reasons why this happened, and why I needed to do that, so I cannot confirm that is the "proper" way of doing things. My gut would tell me that I had something missing in my config file; I can't imagine why Spring would not scan for #Aspect beans.
The other thing you can do, is to explicitly declare your Aspect bean in the XML config file as well to see if this the same type of problem you're having.
You can also enable debug logging in the Spring framework and see if your bean is being loaded by Spring. If not, then it gives you an idea where to start looking.
I'm trying to test out Spring Annotations to see how they work with some simple examples derived from the Spring 3.0 Source (in this case the "#Required" annotation specifically).
To start, I came up with a basic "Hello World" type example that doesn't use any annotations. This works as expected (i.e. prints "Hello Spring 3.0~!").
I then added a DAO object field to the Spring3HelloWorld class. My intention was to deliberately cause an exception to occur by annotating the setter for the DAO with #Required but then not setting it. However, I get a null pointer exception (since this.dao is null) when I was expecting an exception based on not following the annotation "rules/requirements".
I thought I would have needed to set the DAO object before calling any method from Spring3HelloWorld, but apparently that's not the case. I assume I'm misunderstanding how #Required works.
So basically how would I get the following to give me an error along the lines of "Hey you can't do that, you forgot to set DAO blah blah blah".
Spring3HelloWorldTest.java:
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class Spring3HelloWorldTest {
public static void main(String[] args) {
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource ("SpringHelloWorld.xml"));
Spring3HelloWorld myBean = (Spring3HelloWorld) beanFactory.getBean("spring3HelloWorldBean");
myBean.sayHello();
}
}
Spring3HelloWorld.java:
import org.springframework.beans.factory.annotation.Required;
public class Spring3HelloWorld {
private DAO dao;
#Required
public void setDAO( DAO dao ){
this.dao = dao;
}
public void sayHello(){
System.out.println( "Hello Spring 3.0~!" );
//public field just for testing
this.dao.word = "BANANA!!!";
}
}
SpringHelloWorld.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
<bean id="dao" class="src.DAO" ></bean>
<bean id="spring3HelloWorldBean" class="src.Spring3HelloWorld" ></bean>
</beans>
My first guess is you won't get any of the advanced behaviour with Spring and annotations because you are using an XmlBeanFactory instead of the recommended ApplicationContext.
-- edit --
Yup - see this Stack Overflow question/answer.
The following test illustrates that this test bean is initialized twice by Spring. I'm hoping someone can tell me why this is so, since it should only be once. Here's the test:
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {} )
public class TestAfterPropsSet implements InitializingBean {
private static final Logger logger = Logger.getLogger(TestAfterPropsSet.class);
#Test
public void test1() {
logger.debug("Test1");
}
#Test
public void test2() {
logger.debug("Test2");
}
public void afterPropertiesSet() throws Exception {
logger.debug("Bean Initialized");
}
} // end class
Here's the bean file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
and here's the output:
2009-10-13 21:20:04,393 [TestAfterPropsSet.java 26] DEBUG - Bean Initialized
2009-10-13 21:20:04,393 [TestAfterPropsSet.java 17] DEBUG - Test1
2009-10-13 21:20:04,393 [TestAfterPropsSet.java 26] DEBUG - Bean Initialized
2009-10-13 21:20:04,393 [TestAfterPropsSet.java 22] DEBUG - Test2
It's not a Spring convention. You should be following JUnit conventions, i.e. suite-wide initialization or deconstruction should be done in #BeforeClass and #AfterClass accordingly, or you can use #Autowire and let Spring handle the object's scope.
A new suite will be constructed for each test. This is more apparent in JUnit3 where you had to create a new suite using a specified test name.
Take a look at the JavaDoc:
The Test annotation tells JUnit that
the public void method to which it is
attached can be run as a test case. To
run the method, JUnit first constructs
a fresh instance of the class then
invokes the annotated method. Any
exceptions thrown by the test will be
reported by JUnit as a failure. If no
exceptions are thrown, the test is
assumed to have succeeded.
Your use case is a bit puzzling since your test isn't actually doing anything and there is no bean, which you reference. By default, Spring beans are declared with the default scope="singleton" attribute, so had you actually declared a bean, it would have been a cached singleton. However, this has nothing to do with method execution.