这次说说怎么对Service层方法进行测试,同时弄清楚怎么来处理@Resource、@Autowired属性。
通过实例来描述:
有一个Service类,如下:
public class SysEmployeeService{
@Resource
private SysEmployeeDao sysEmployeeDao;
/**
*
* 获取所有员工信息.
*
* @param page
* 页数
* @param rows
* 条数
* @return Object
*/
public Pagination<Object> getAllEmployees(int page, int rows) {
return this.sysEmployeeDao.getAllEmployees(page, rows);
}
}
现在要对getAllEmployees方法进行单元测试,代码如下:
/**
* @author lisanlai <br />
* Mail: sanlai_lee@qq.com <br />
* Blog:http://blog.lisanlai.cn <br />
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/META-INF/spring/sellmanager-context.xml",
"/META-INF/spring/dao-context.xml",
"/META-INF/spring/mvc-context.xml" })
public class SysEmployeeServiceTest {
@Resource
private SysEmployeeService sysEmployeeService;
/**
* Test method for {@link com.cmcc.zysoft.sysmanage.service.SysEmployeeService#getAllEmployees(int, int)}.
*/
@Test
public void testGetAllEmployees() {
IMocksControl control = EasyMock.createControl();
//创建虚拟对象
SysEmployeeDao mockSysEmployeeDao = control.createMock(SysEmployeeDao.class);
int page = 1;
int rows = 20;
//创建虚拟对象方法期望的返回值
int totalPages = 20;
int offset = 1;
int limit = 20;
int totalRecords = 400;
Pagination<Object> pagination = new Pagination<Object>(totalPages, offset, limit, totalRecords);
//录制动作
EasyMock.expect(mockSysEmployeeDao.getAllEmployees(page, rows)).andReturn(pagination) ;
//回放动作
control.replay();
//用spring提供的方法注入aurowired的字段
ReflectionTestUtils.setField(
unwrap(sysEmployeeService),
"sysEmployeeDao",
mockSysEmployeeDao,
SysEmployeeDao.class);
//执行测试方法
Pagination<Object> p = sysEmployeeService.getAllEmployees(page, rows);
Assert.assertArrayEquals("SysEmployeeService.GetAllEmployees方法逻辑错误",
new int[]{totalPages,offset,limit,totalRecords},
new int[]{(int)p.getTotalPages(),p.getOffset(),p.getLimit(),(int)p.getTotalRecords()});
//验证是否使用了上面录制的DAO
EasyMock.verify(mockSysEmployeeDao);
}
/**
* Method Name:unwrap .
* @param proxiedInstance
* @return
* the return type:T
*/
@SuppressWarnings("unchecked")
public static <T> T unwrap(T proxiedInstance) {
if (proxiedInstance instanceof Advised) {
try {
return unwrap((T) ((Advised) proxiedInstance).getTargetSource().getTarget());
} catch (Exception e) {
Assert.fail("对代理对象进行unwrap发生异常:" + proxiedInstance.getClass());
}
}
return proxiedInstance;
}
}
虽然上面这段代码只是一个实例,但是它已经很好的遵守了单元测试的原则,实现了方法之前的隔离,对于部分人估计对这个代码理解有点困难,因为没弄清楚什么是隔离,为什么要隔离。
对于@Resource、@Autowired属性,我们可以利用Spring提供的一个类来处理:ReflectionTestUtils
例如上面的:
ReflectionTestUtils.setField(
unwrap(sysEmployeeService),
"sysEmployeeDao",
mockSysEmployeeDao,
SysEmployeeDao.class);
通过实例来描述:
有一个Service类,如下:
public class SysEmployeeService{
@Resource
private SysEmployeeDao sysEmployeeDao;
/**
*
* 获取所有员工信息.
*
* @param page
* 页数
* @param rows
* 条数
* @return Object
*/
public Pagination<Object> getAllEmployees(int page, int rows) {
return this.sysEmployeeDao.getAllEmployees(page, rows);
}
}
现在要对getAllEmployees方法进行单元测试,代码如下:
/**
* @author lisanlai <br />
* Mail: sanlai_lee@qq.com <br />
* Blog:http://blog.lisanlai.cn <br />
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/META-INF/spring/sellmanager-context.xml",
"/META-INF/spring/dao-context.xml",
"/META-INF/spring/mvc-context.xml" })
public class SysEmployeeServiceTest {
@Resource
private SysEmployeeService sysEmployeeService;
/**
* Test method for {@link com.cmcc.zysoft.sysmanage.service.SysEmployeeService#getAllEmployees(int, int)}.
*/
@Test
public void testGetAllEmployees() {
IMocksControl control = EasyMock.createControl();
//创建虚拟对象
SysEmployeeDao mockSysEmployeeDao = control.createMock(SysEmployeeDao.class);
int page = 1;
int rows = 20;
//创建虚拟对象方法期望的返回值
int totalPages = 20;
int offset = 1;
int limit = 20;
int totalRecords = 400;
Pagination<Object> pagination = new Pagination<Object>(totalPages, offset, limit, totalRecords);
//录制动作
EasyMock.expect(mockSysEmployeeDao.getAllEmployees(page, rows)).andReturn(pagination) ;
//回放动作
control.replay();
//用spring提供的方法注入aurowired的字段
ReflectionTestUtils.setField(
unwrap(sysEmployeeService),
"sysEmployeeDao",
mockSysEmployeeDao,
SysEmployeeDao.class);
//执行测试方法
Pagination<Object> p = sysEmployeeService.getAllEmployees(page, rows);
Assert.assertArrayEquals("SysEmployeeService.GetAllEmployees方法逻辑错误",
new int[]{totalPages,offset,limit,totalRecords},
new int[]{(int)p.getTotalPages(),p.getOffset(),p.getLimit(),(int)p.getTotalRecords()});
//验证是否使用了上面录制的DAO
EasyMock.verify(mockSysEmployeeDao);
}
/**
* Method Name:unwrap .
* @param proxiedInstance
* @return
* the return type:T
*/
@SuppressWarnings("unchecked")
public static <T> T unwrap(T proxiedInstance) {
if (proxiedInstance instanceof Advised) {
try {
return unwrap((T) ((Advised) proxiedInstance).getTargetSource().getTarget());
} catch (Exception e) {
Assert.fail("对代理对象进行unwrap发生异常:" + proxiedInstance.getClass());
}
}
return proxiedInstance;
}
}
虽然上面这段代码只是一个实例,但是它已经很好的遵守了单元测试的原则,实现了方法之前的隔离,对于部分人估计对这个代码理解有点困难,因为没弄清楚什么是隔离,为什么要隔离。
对于@Resource、@Autowired属性,我们可以利用Spring提供的一个类来处理:ReflectionTestUtils
例如上面的:
ReflectionTestUtils.setField(
unwrap(sysEmployeeService),
"sysEmployeeDao",
mockSysEmployeeDao,
SysEmployeeDao.class);