Reputation: 655
I am trying to add mock object in CourseServiceImpl's courseDao field but it is not working.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
locations = {"file:src/main/webapp/WEB-INF/config/servlet-config.xml"}
)
@ActiveProfiles("test")
public final class CourseServiceTest {
@Mock
private CourseDao courseDao;
@Autowired
private CourseService courseService;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testCourseServiceNotNull() {
assertNotNull(courseService);
assertNotNull(courseDao);
ReflectionTestUtils.setField(courseService, "courseDao", courseDao, CourseDao.class);
}
The reflection statement throws an error that field "courseDao" didn't found. But, when I create an object using new operator then it works fine.
ReflectionTestUtils.setField(new CourseServiceImpl(), "courseDao", courseDao, CourseDao.class);
servlet-config.xml
<mvc:annotation-driven />
<mvc:resources location="pdfs" mapping="/pdfs/**" />
<security:global-method-security
pre-post-annotations="enabled" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/view/" p:suffix=".jsp" p:order="2" />
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
p:contentNegotiationManager-ref="contentNegId" p:defaultViews-ref="defaultViewList"
p:order="1" />
<bean id="contentNegId"
class="org.springframework.web.accept.ContentNegotiationManager">
<constructor-arg>
<bean
class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
<constructor-arg>
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
<util:list id="defaultViewList">
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller"
p:autodetectAnnotations="true" />
</constructor-arg>
</bean>
</util:list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"
p:order="0" />
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver"
p:defaultLocale="en" />
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="messages" />
<context:property-placeholder location="classpath:messages.properties" />
<import resource="/hibernate-config.xml" />
<import resource="/hibernate-config-test.xml" />
hibernate-config-test.xml
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/school-repo-test" p:username="user"
p:password="password" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
p:dataSource-ref="myDataSource" p:hibernateProperties-ref="hibernateProps"
p:annotatedClasses-ref="mapClasses">
</bean>
<util:list id="mapClasses">
<value>org.school.model.Course</value>
<value>org.school.model.Role</value>
<value>org.school.model.Staff</value>
<value>org.school.model.Student</value>
<value>org.school.model.Subject</value>
</util:list>
<util:properties id="hibernateProps">
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</util:properties>
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
Apart from profile name, rest is same for hibernate-config file.
CourseServiceImpl
@Service(value = "courseService")
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public class CourseServiceImpl implements CourseService {
@Autowired
private MessageSource messageSource;
@Autowired
private CourseDao courseDao;
@Autowired
private ApplicationContext context;
Please advise.
Upvotes: 4
Views: 6208
Reputation: 1766
Your CourseServiceImpl
class has @Transactional
annotation which means that bean instance wrapped with "Transactional"
proxy before it injected as dependency in CourseServiceTest
and all other beans in Spring context. Such proxy instance hides all the private
fields of original CourseServiceImpl
instance.
So you cannot access fields you want because injected courseService
instance is not the original CourseServiceImpl
class any more, it is dynamic cglib
or JDK
proxy class.
Upvotes: 2