@RunWith(SpringJUnit4ClassRunner.class) // 整合
@ContextConfiguration(locations = {"classpath:spring/application*.xml"}) // 加载配置
@TransactionConfiguration(transactionManager = "transactionManager")
@Transactional
public class UserServiceTest {
/**(被注入的对象)
* 该注解的对象也被mock了,(一般情况下)除了@mock的对象能注入,
* 在UserServiceImpl类内部的其他@Autowired属性都为null
*/
@InjectMocks
UserServiceImpl userService = mock(UserServiceImpl.class);
/**
* 注入到UserServiceImpl中,也就是注入到@InjectMocks标注的对象
*/
@Mock
private UserApiService userApiService;
/**
*因为该属性不需要被mock,但单元测试需要调用到该对象的方法,因此需要执行
* ReflectionTestUtils.setField(
* AopTargetUtils.getTarget(userService),"wechatApiService",wechatApiService);
* 来为userService对象设置属性
* (@Reference和@Autowired同类型)
*/
@Reference
private WechatApiService wechatApiService;
String userId = "asdfasdfasdfasdf";
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
//构造数据
UserResultDto userResultDto = new UserResultDto();
userResultDto.setUsername("hello");
userResultDto.setNickName("world");
userResultDto.setPhone("18825153385");
ReflectionTestUtils.setField(AopTargetUtils.getTarget(userService),"wechatApiService",wechatApiService);
Mockito.when(userApiService.getUserById(userId)).thenReturn(userResultDto);
//需要告诉被@InjectMocks修饰的对象去调用真实的方法,否则单元测试方法中的被@InjectMocks修饰的对象不会调用真正的getUserInfoByUserId方法
doCallRealMethod().when(userService).getUserInfoByUserId(userId);
}
@Test
public void testetUserInfoByUserId() {
UserInfoVo userInfoVo = userService.getUserInfoByUserId(userId);
Assert.assertEquals(null, userInfoVo);
}
}
AopTargetUtils类的代码:
public class AopTargetUtils {
/**
* 获取 目标对象
*
* @param proxy 代理对象
* @return
* @throws Exception
*/
public static Object getTarget(Object proxy) throws Exception {
if (!AopUtils.isAopProxy(proxy)) {
return proxy;//不是代理对象
}
if (AopUtils.isJdkDynamicProxy(proxy)) {
return getJdkDynamicProxyTargetObject(proxy);
} else { //cglib
return getCglibProxyTargetObject(proxy);
}
}
private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
h.setAccessible(true);
Object dynamicAdvisedInterceptor = h.get(proxy);
Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
advised.setAccessible(true);
return ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
}
private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
h.setAccessible(true);
AopProxy aopProxy = (AopProxy) h.get(proxy);
Field advised = aopProxy.getClass().getDeclaredField("advised");
advised.setAccessible(true);
return ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();
}
}
最后感谢这两篇文章:
http://xiahaihuje.iteye.com/blog/2174150
http://www.cnblogs.com/syxchina/p/4150879.html