Mocking DAO object with MockMvc in Spring Boot - spring-boot

I am new to Integration testing. I have Spring Integration application for which I am writing test cases. here is how I am writing test case:
Activator:
#Service
public class ProdAppActivator {
#Autowired
private ApplicantDAO applicantDAO;
#Transactional
public ApplicantDTO prodApp(ApplicantDTO applicant)
throws TechnicalException, BusinessException {
applicantDAO.updateApp(applicant);
return application;
}
}
Test Class:
public class AcctImplTest extends AbstractTest {
#MockBean
private ApplicantDAO applicantDAO;
#Override
#Before
public void setUp() {
super.setUp();
}
#Test
public void testProdApp() throws Exception {
ProdAppRequest appRequest = getProdAppRequest();
mvc.perform(post("/baseurl/applicant").headers(getHeaders()).accept(MediaType.APPLICATION_JSON)
.content(mapToJson(appRequest)).contentType(MediaType.APPLICATION_JSON)).andDo(print())
.andExpect(status().isOk());
}
}
AbstractTest:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:group/deposit/svc/product-application-context-test.xml" })
#WebMvcTest
//#IfProfileValue(name ="profiles.active", value ="Integration")
public abstract class AbstractTest {
protected MockMvc mvc;
#Autowired
WebApplicationContext webApplicationContext;
protected void setUp() {
setCMD();
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
I have 2 issues:
This activator has a method with #Transactional annotation. I am not sure why but because of this annotation my test getting failed and giving error as:
java.lang.ClassLoader.loadClass(ClassLoader.java:424)
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
java.lang.ClassLoader.loadClass(ClassLoader.java:357)
org.springframework.orm.hibernate4.HibernateTransactionManager.isSameConnectionForEntireSession(HibernateTransactionManager.java:711)
org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:445)
org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:378)
org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:474)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:289)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
com.hsbc.group.depositproduct.us.svc.activators.RecordProdAppActivator$$EnhancerBySpringCGLIB$$d1f3f882.recordProdApp(<generated>)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
When I remove this annotation everything works fine. But I don't want to remove this annotation so can some please suggest how to write test here.
if I remove #Transactional annotation; I have used #MockBean to mock DAO object(Interface) and its mocking given object but when I try to return expected value for any DAO call its returning default value. Can some one please suggest how to mock DAO while using #MockBean. I have tried #SpyBean, and other possible ways but didn't get success.
Thanks in advance.

Related

Cannot run Unit Tests against REST layer

I cannot unit test the web layer using jhipster (according to spring gs guides):
#RunWith(SpringRunner.class)
#WebMvcTest
public class FlightControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private FlightService flightService;
#Test
public void testCreate() throws Exception {
FlightDto expected = new FlightDto();
ReflectionTestUtils.setField(expected, "id", 1L);
when(flightService.createFlight(any(FlightDto.class))).thenReturn(expected);
FlightDto flightDto = new FlightDto();
flightDto.setNumber("CAI-123400");
this.mockMvc.perform(post("/api/flight")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(flightDto)))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(header().string("Location", endsWith("/api/flight/1")));
}
}
The above Unit test success in case of green-field spring boot project, but fails in case of green-field spring boot-based jhipster project:
When run Unit Test in jhispter project (springboot-with-jhipster) from FlightResource I got:
java.lang.IllegalStateException: Unable to find a #SpringBootConfiguration, you need to use #ContextConfiguration or #SpringBootTest(classes=...) with your test
at org.springframework.util.Assert.state(Assert.java:70)
at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.getOrFindConfigurationClasses(SpringBootTestContextBootstrapper.java:202)
at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.processMergedContextConfiguration(SpringBootTestContextBootstrapper.java:137)
at org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper.processMergedContextConfiguration(WebMvcTestContextBootstrapper.java:35)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:409)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:323)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:277)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildTestContext(AbstractTestContextBootstrapper.java:112)
at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.buildTestContext(SpringBootTestContextBootstrapper.java:82)
at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:120)
at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:105)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:152)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:143)
at org.springframework.test.context.junit4.SpringRunner.<init>(SpringRunner.java:49)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
I can run the test with this code:
#RunWith(SpringRunner.class)
//#WebMvcTest remove #WebMvcTest
//add SpringBootTest
#SpringBootTest(classes = JhUnittestRestApp.class)
public class FlightResourceTest {
//#Autowired remove anotation
private MockMvc mockMvc;
#MockBean
private FlightService flightService;
#Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
#Autowired
private PageableHandlerMethodArgumentResolver pageableArgumentResolver;
#Autowired
private ExceptionTranslator exceptionTranslator;
#Before
public void setup() {
//initialize the bean
MockitoAnnotations.initMocks(this);
final FlightResource flightResource = new FlightResource(flightService);
this.mockMvc = MockMvcBuilders.standaloneSetup(flightResource)
.setCustomArgumentResolvers(pageableArgumentResolver)
.setControllerAdvice(exceptionTranslator)
.setConversionService(createFormattingConversionService())
.setMessageConverters(jacksonMessageConverter).build();
}
#Test
public void testCreate() throws Exception {
FlightDTO expected = new FlightDTO();
ReflectionTestUtils.setField(expected, "id", 1L);
when(flightService.save(any(FlightDTO.class))).thenReturn(expected);
FlightDTO flightDto = new FlightDTO();
flightDto.setNumber("CAI-123400");
//update the url to /api/flights so that the test can pass
this.mockMvc.perform(post("/api/flights")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(flightDto)))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(header().string("Location", endsWith("/api/flights/1")));
}
}
Your FlightControllerTest is working in your springboot-no-jhipster project because the main class of the project is annotated with #SpringBoot According to the documentation of #SpringBoot
The #SpringBootApplication annotation is equivalent to using:
#Configuration, #EnableAutoConfiguration and #ComponentScan with their default attributes
Since JHipster needs some more configuration than just the default, JHipster is not using #SpringBootApplication as you can see in your project. This is perfectly OK and works without problems.
On the other hand the error message of your test is saying that it can't detect #SpringBootConfiguration. There are other annotation e.g. #ContextConfiguration or #SpringBootTest that are rocomandet to use for the test. Actually there are some inconsistencies on which annotation in main config class fits with the test annotations see here or here.

spring test fails on mockServletContext unsupportedOperation

I have a set of Integration Tests running for my Spring-Boot 1.3 app. But I had to add the following to get my maximum sessions working:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ServletContextAware {
...
#Override
public void setServletContext(ServletContext servletContext) {
servletContext.getSessionCookieConfig().setHttpOnly(true);
// causes an ApplicationEvent to be published to the Spring ApplicationContext every time a HttpSession commences or terminates
servletContext.addListener(new HttpSessionEventPublisher());
}
...
}
Now when I run my tests, I get the following:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig' defined in file [/Users/davidclark/projects/edmtotal/build/classes/main/com/edelweissco/dental/configuration/WebSecurityConfig.class]: Initialization of bean failed; nested exception is java.lang.UnsupportedOperationException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
...
Caused by: java.lang.UnsupportedOperationException
at org.springframework.mock.web.MockServletContext.addListener(MockServletContext.java:675)
at com.edelweissco.dental.configuration.WebSecurityConfig.setServletContext(WebSecurityConfig.java:123)
...
Here is an example test class (but they all fall with the same exception):
#Transactional
public class ConfigurationSettingsTest extends BaseSpecification {
#Autowired
private ConfigurationSettings configurationSettings;
#Autowired
ConfigurableApplicationContext context
...
}
where BaseSpecification is:
#ContextConfiguration(classes = MyApp, loader = SpringApplicationContextLoader)
#WebAppConfiguration
public class BaseSpecification extends Specification {
#Value('${local.server.port}')
private int serverPort;
def setup() {
RestAssured.port = serverPort;
}
}
It would seem that now when I run my integration tests, a MockServlet is being applied here, and it doesn't support. this feature. When debugging, I see that a SpringBootMockServletContext is trying to be set in setServletContext, and that is where the exception is.
I will post my answer in case anyone else runs into this. The problem was in my BaseSpecification. I added the #WebAppConfiguration and #IntegrationTest to it, and removed #IntegrationTest off the individual integration tests. Apparently this will actually create the ServletContext the way it should be.
#ContextConfiguration(classes = MyApp, loader = SpringApplicationContextLoader)
#WebAppConfiguration
#IntegrationTest
public class BaseSpecification extends Specification {

Issue injecting #Context in resource class

I'm having difficulties injecting HttpHeaders into my rest service class.
#Path("/account")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
#Transactional
#Service
public class UserServiceImpl implements UserService {
#Context
private HttpHeaders headers;
#Override
#POST #Path("/{username}/")
public User get(#PathParam(value = "username") String username)
throws UnknownUserException {
String requestId = headers.getHeaderString("requestId");
return new User();
}
}
When I try running the application I get the following exception during the spring initialisation:
Caused by: java.lang.IllegalArgumentException: Can not set javax.ws.rs.core.HttpHeaders field com.acme.service.UserServiceImpl.headers to com.sun.proxy.$Proxy50
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
at java.lang.reflect.Field.set(Field.java:758)
at org.apache.cxf.jaxrs.utils.InjectionUtils$1.run(InjectionUtils.java:192)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.cxf.jaxrs.utils.InjectionUtils.injectFieldValue(InjectionUtils.java:188)
at org.apache.cxf.jaxrs.utils.InjectionUtils.injectContextProxiesAndApplication(InjectionUtils.java:1058)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.injectContexts(JAXRSServerFactoryBean.java:405)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.updateClassResourceProviders(JAXRSServerFactoryBean.java:429)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:162)
A bit of experimenting shows that I get the same error when trying to inject anything. I have an exception mapper that has the http headers injected in do problem what so ever, so I created a custom provider to obtain the headers but get the same problem injecting that in.
I'm pretty sure I must be missing something fundamental here.
I know that I could add what I need out of the headers as params to the method but I can't change the interface.
Adding the context to the operation
#Override
#POST #Path("/{username}/")
public User get(#Context HttpHeaders httpHeaders, #PathParam(value = "username") String username)
Gives me the following error.
java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:181)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:97)
I've discovered that if I drop the implements interface then the application actually starts, however nothing is actually injected in.
I've found a workaround (or possibly the expected solution). It appears that spring is using a proxy based on the interface. I created an intermediate interface and stuck on a setHttpHeaders operation on the interface and annotated the implementation with #Context. All seems fine with that.
public interface MyService {
void doStuff();
}
public interface MyServiceInt extends MyService {
void setHttpHeaders(HttpHeaders headers);
}
#Path("/")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
#Transactional
#Service
public class MyServiceImpl implements MyServiceInt {
private HttpHeaders httpHeaders;
#Context
void setHttpHeaders(HttpHeaders headers) {
this.httpHeaders = httpHeaders;
}
#Override
#POST #Path("/doStuff")
public void doStuff() {
}
}
Would still like to hear of a better solution if anyone knows.

JPA. No transactional EntityManager available

I'm use JPA (Hibernate 4 vendor) and Spring 3.2.x.
I use this code for get Session and re-attach my detached entity.
Session session = entityManager.unwrap(Session.class);
My code look like this :
#Service
public class SchedulerServiceImpl implements SchedulerService {
#PersistenceContext
private EntityManager entityManager;
#Override
#Transactional
#Scheduled(fixedDelay = 5000)
public void executeTasks() {
.. code ..
while (tasksIterator.hasNext()) {
SchedulerTask readyTask = recalculation(currentTask);
}
.. code ...
}
#Override
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public Deposit recalculation(SchedulerTask schedulerTask) {
boolean asda = entityManager.isOpen(); // get TRUE
Session session = entityManager.unwrap(Session.class); // Exception here
session.update(schedulerTask);
... code ...
}
}
What's wrong?
error :
00:21:52,180 ERROR [org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler]
(pool-10-thread-1) Unexpected error occurred in scheduled task.:
java.lang.IllegalStateException: No transactional EntityManager
available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invokeSharedEntityManagerCreator.java:224)
[spring-orm-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at com.sun.proxy.$Proxy36.unwrap(Unknown Source)
at com.jar.dom.service.SchedulerServiceImpl.recalculation(SchedulerServiceImpl.java:133)
[classes:]
at com.jar.dom.service.SchedulerServiceImpl.executeTasks(SchedulerServiceImpl.java:92)
[classes:]
I solved this adding this lines on spring configuration
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories("com.blablabla")
class ApplicationConfig {
....
}

How do I inject mocks into a Spring class marked as "#Transactional"?

I'm using SPring 3.1.1.RELEASE and JUnit 4.8.1. In my test class, I want to mock a private field and discovered the beauty of "ReflectionTestUtils" ...
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({ "classpath:test-context.xml" })
public class OrderServiceTest extends AbstractTransactionalJUnit4SpringContextTests
…
#Autowired
private OrderService m_orderSvc;
#Test
public void testGetPDOrders() throws QuickBaseException, Exception {
…
ReflectionTestUtils.setField(m_orderSvc, "m_orderDao", mockOrderDao);
Below is the class and field I'm trying to mock ...
#Service("orderService")
#Transactional
public class OrderServiceImpl implements OrderService {
…
#Autowired
private OrderDAO m_orderDao;
Disappointingly, I get the below error. I've read that this is because my class is marked as "#Transactional" but I can't find an adequate work-around and it seems like a waste to write setter methods solely to accommodate JUnit. Does anyone have another suggestion about how I can inject my mock object into a private field?
java.lang.IllegalArgumentException: Could not find field [m_orderDao] on target [org.mainco.subco.myclient.service.OrderServiceImpl#282f0e07]
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.test.util.ReflectionTestUtils.setField(ReflectionTestUtils.java:107)
at org.springframework.test.util.ReflectionTestUtils.setField(ReflectionTestUtils.java:84)
at org.mainco.subco.myclient.service.OrderServiceTest.testGetPDOrders(OrderServiceTest.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
I'm not sure what mocking library you're using, but there is a helpful integration between Spring and Mockito aptly and clumsily named "Springockito" that can make tactical insertions of mocks in a greater Spring context pretty easy.
The idea is that you change your test application context to map that bean to a mock, rather than try to wire the mock to your parent bean at runtime.
So really you just end up with:
text-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
...
xmlns:mockito="http://www.mockito.org/spring/mockito"
xsi:schemaLocation="... http://www.mockito.org/spring/mockito https://bitbucket.org/kubek2k/springockito/raw/tip/springockito/src/main/resources/spring/mockito.xsd">
<mockito:mock id="m_orderDao" class="my.package.OrderDao"/>
<!--... other config ...-->
</beans>
Then you can just autowire the mock itself into your test if you need to interact with it, the same way you are doing for your service as it stands now.
If you're not using Mockito, you can still use the approach above, but instead use your mocking library's method for creating mocks as the factory for the bean.
As of 2014 the easiest solution is to use #InjectMocks annotation that is part of Mockito. This works with any class including the ones marked with #Transactional.
Here is an example :
public class TestTestController {
#Mock
private TestService testService;
#InjectMocks
private TestController testController;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testMocks() throws Exception {
String mockedReturnValue = "this is a mocked reply";
when(testService.getMessage()).thenReturn(mockedReturnValue);
assertEquals(mockedReturnValue, testController.callTestService());
}
}
and the related classes
public class TestController {
#Autowired
private TestService testService;
public String callTestService() {
return testService.getMessage();
}
}
public class TestService {
public static final String THIS_IS_A_TEST = "this is a getMessage";
public String getMessage() {
return THIS_IS_A_TEST;
}
}

Resources