Easymock:mock 正在执行
Easymock: mock is being executed
所以这是我第一次使用 EasyMock,我正在尝试向一些遗留代码添加一些单元测试。
遗留代码在 Spring 3.1 中,我使用的是 EasyMock 3.4。
我想在这里完成的是测试调用dao 的服务(用Spring 编写的方法)。
代码如下:
@Entity
@Table(name="comment")
public class CommentBO{
public static CommentBO createNewComment(Integer clientNumber, Integer commentCategory){
CommentBO bo = new CommentBO();
bo.setClientNumber(clientNumber);
bo.setCommentCategory(commentCategory);
return bo;
}
}
public interface AssessmentService {
public CommentBO getComment(Integer clientNumber, Integer
commentCategory);
}
public class AssessmentServiceImpl implements
AssessmentService {
@Resource(name = "com.client.assessment.bl.dao.AssessmentDao")
private AssessmentDao assessmentDao;
@Override
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public CommentBO getComment(Integer clientNumber,Integer commentCategory) {
CommentBO comment = this.assessmentDao.getComment(
clientNumber, commentCategory);
if (comment != null && comment.getComments() != null) {
comment.setComments(comment.getComments().replaceAll("<li>•",
"<li>"));
}
return comment;
}
public interface AssessmentDao {
public CommentBO getComment(Integer clientNumber, Integer commentCategory);
}
@Repository(value = "com.client.assessment.bl.dao.AssessmentDao")
public class AssessmentDaoImpl implements AssessmentDao {
@Override
public CommentBO getComment(Integer clientNumber, Integer
commentCategory) {
Criteria criteria =
this.getSession(false).createCriteria(CommentBO.class);
criteria.add(Restrictions.eq("clientNumber", clientNumber))
.add(Restrictions.eq("commentCategory", commentCategory));
if (criteria.list() != null && criteria.list().size() > 0) {
return (CommentBO) criteria.list().get(0);
}
return null;
}
}
这是我用 EasyMock 编写的单元测试
@SpringApplicationContext("classpath*:/com/client/assessment/**/*-context.xml")
public class AssessmentServiceTest extends UnitilsJUnit4 {
@SpringBean("com.client.assessment.remote.AssessmentService")
public AssessmentService assessmentService = null;
@Test
public void testGetComment(){
Integer clientNumber = 1;
Integer commentCategory = 1;
CommentBO commentBO = CommentBO.createNewComment(clientNumber, commentCategory);
AssessmentDao assessmentDao = EasyMock.createMock(AssessmentDao.class);
EasyMock.expect(assessmentDao.getComment((Integer) anyObject(), (Integer) anyObject())).andReturn(commentBO).anyTimes();
ReflectionTestUtils.setField(assessmentService, "assessmentDao", assessmentDao);
EasyMock.replay(assessmentDao);
CommentBO bo = assessmentService.getComment(clientNumber, commentCategory);
assertThat( bo , instanceOf(CommentBO.class));
}
}
所以基本上发生的事情是,我的单元测试失败了,因为
assessmentService.getComment(clientNumber, commentCategory);
为空!
是的,如果实际执行它,它将为空,因为在数据库中没有 clientNumber = 1 和 commentCategory = 1 的记录。
这就是为什么,我想嘲笑所说的 dao 并将其强制为 return CommentBO 对象。
正如我上面所说,这是我第一次使用 EasyMock,所以我在这里遗漏了一些明显的东西吗?我是否需要模拟 dao 方法中的调用(即 AssessmentDao 的 getComment)?但如果我这样做,我将被迫嘲笑 Criteria 对象等,我认为这是不好的做法?
当前代码应该可以工作。所以我看到的唯一可能性是 getComment
实际上是最终的。如果删除 anyTimes
并在断言前添加 verify
,您应该会看到缺少调用。
唯一的另一种可能性是 ReflectionTestUtils
默默地失败了。所以您仍然注入了原始的 spring bean。如果你调试,你会很容易地看到服务中注入的 DAO 不是 mock。
我已经在下方重写了您的代码。效果很好。
public interface AssessmentDao {
CommentBO getComment(Integer clientNumber, Integer commentCategory);
}
public class AssessmentDaoImpl implements AssessmentDao {
@Override
public CommentBO getComment(Integer clientNumber, Integer commentCategory) {
throw new AssertionError("Should not be called");
}
}
public interface AssessmentService {
CommentBO getComment(Integer clientNumber, Integer commentCategory);
}
public class AssessmentServiceImpl implements AssessmentService {
private AssessmentDao assessmentDao;
@Override
public CommentBO getComment(Integer clientNumber, Integer commentCategory) {
CommentBO comment = this.assessmentDao.getComment(clientNumber, commentCategory);
if (comment != null && comment.getComments() != null) {
comment.setComments(comment.getComments().replaceAll("<li>•", "<li>"));
}
return comment;
}
}
public class CommentBO {
public static CommentBO createNewComment(Integer clientNumber, Integer commentCategory) {
CommentBO bo = new CommentBO();
bo.setClientNumber(clientNumber);
bo.setCommentCategory(commentCategory);
return bo;
}
private Integer clientNumber;
private Integer commentCategory;
private String comments;
public Integer getClientNumber() {
return clientNumber;
}
public void setClientNumber(Integer clientNumber) {
this.clientNumber = clientNumber;
}
public Integer getCommentCategory() {
return commentCategory;
}
public void setCommentCategory(Integer commentCategory) {
this.commentCategory = commentCategory;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
}
public class ReflectionTestUtils {
public static void setField(Object object, String fieldName, Object value) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
}
catch(Exception e) {
throw new RuntimeException(e);
}
}
}
public class AssessmentServiceTest {
public AssessmentService assessmentService = new AssessmentServiceImpl();
@Test
public void testGetComment(){
Integer clientNumber = 1;
Integer commentCategory = 1;
CommentBO commentBO = CommentBO.createNewComment(clientNumber, commentCategory);
AssessmentDao assessmentDao = EasyMock.createMock(AssessmentDao.class);
expect(assessmentDao.getComment(anyObject(), anyObject())).andReturn(commentBO);
ReflectionTestUtils.setField(assessmentService, "assessmentDao", assessmentDao);
replay(assessmentDao);
CommentBO bo = assessmentService.getComment(clientNumber, commentCategory);
verify(assessmentDao);
assertThat(bo , instanceOf(CommentBO.class));
}
}
所以这是我第一次使用 EasyMock,我正在尝试向一些遗留代码添加一些单元测试。
遗留代码在 Spring 3.1 中,我使用的是 EasyMock 3.4。
我想在这里完成的是测试调用dao 的服务(用Spring 编写的方法)。
代码如下:
@Entity
@Table(name="comment")
public class CommentBO{
public static CommentBO createNewComment(Integer clientNumber, Integer commentCategory){
CommentBO bo = new CommentBO();
bo.setClientNumber(clientNumber);
bo.setCommentCategory(commentCategory);
return bo;
}
}
public interface AssessmentService {
public CommentBO getComment(Integer clientNumber, Integer
commentCategory);
}
public class AssessmentServiceImpl implements
AssessmentService {
@Resource(name = "com.client.assessment.bl.dao.AssessmentDao")
private AssessmentDao assessmentDao;
@Override
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public CommentBO getComment(Integer clientNumber,Integer commentCategory) {
CommentBO comment = this.assessmentDao.getComment(
clientNumber, commentCategory);
if (comment != null && comment.getComments() != null) {
comment.setComments(comment.getComments().replaceAll("<li>•",
"<li>"));
}
return comment;
}
public interface AssessmentDao {
public CommentBO getComment(Integer clientNumber, Integer commentCategory);
}
@Repository(value = "com.client.assessment.bl.dao.AssessmentDao")
public class AssessmentDaoImpl implements AssessmentDao {
@Override
public CommentBO getComment(Integer clientNumber, Integer
commentCategory) {
Criteria criteria =
this.getSession(false).createCriteria(CommentBO.class);
criteria.add(Restrictions.eq("clientNumber", clientNumber))
.add(Restrictions.eq("commentCategory", commentCategory));
if (criteria.list() != null && criteria.list().size() > 0) {
return (CommentBO) criteria.list().get(0);
}
return null;
}
}
这是我用 EasyMock 编写的单元测试
@SpringApplicationContext("classpath*:/com/client/assessment/**/*-context.xml")
public class AssessmentServiceTest extends UnitilsJUnit4 {
@SpringBean("com.client.assessment.remote.AssessmentService")
public AssessmentService assessmentService = null;
@Test
public void testGetComment(){
Integer clientNumber = 1;
Integer commentCategory = 1;
CommentBO commentBO = CommentBO.createNewComment(clientNumber, commentCategory);
AssessmentDao assessmentDao = EasyMock.createMock(AssessmentDao.class);
EasyMock.expect(assessmentDao.getComment((Integer) anyObject(), (Integer) anyObject())).andReturn(commentBO).anyTimes();
ReflectionTestUtils.setField(assessmentService, "assessmentDao", assessmentDao);
EasyMock.replay(assessmentDao);
CommentBO bo = assessmentService.getComment(clientNumber, commentCategory);
assertThat( bo , instanceOf(CommentBO.class));
}
}
所以基本上发生的事情是,我的单元测试失败了,因为
assessmentService.getComment(clientNumber, commentCategory);
为空!
是的,如果实际执行它,它将为空,因为在数据库中没有 clientNumber = 1 和 commentCategory = 1 的记录。
这就是为什么,我想嘲笑所说的 dao 并将其强制为 return CommentBO 对象。
正如我上面所说,这是我第一次使用 EasyMock,所以我在这里遗漏了一些明显的东西吗?我是否需要模拟 dao 方法中的调用(即 AssessmentDao 的 getComment)?但如果我这样做,我将被迫嘲笑 Criteria 对象等,我认为这是不好的做法?
当前代码应该可以工作。所以我看到的唯一可能性是 getComment
实际上是最终的。如果删除 anyTimes
并在断言前添加 verify
,您应该会看到缺少调用。
唯一的另一种可能性是 ReflectionTestUtils
默默地失败了。所以您仍然注入了原始的 spring bean。如果你调试,你会很容易地看到服务中注入的 DAO 不是 mock。
我已经在下方重写了您的代码。效果很好。
public interface AssessmentDao {
CommentBO getComment(Integer clientNumber, Integer commentCategory);
}
public class AssessmentDaoImpl implements AssessmentDao {
@Override
public CommentBO getComment(Integer clientNumber, Integer commentCategory) {
throw new AssertionError("Should not be called");
}
}
public interface AssessmentService {
CommentBO getComment(Integer clientNumber, Integer commentCategory);
}
public class AssessmentServiceImpl implements AssessmentService {
private AssessmentDao assessmentDao;
@Override
public CommentBO getComment(Integer clientNumber, Integer commentCategory) {
CommentBO comment = this.assessmentDao.getComment(clientNumber, commentCategory);
if (comment != null && comment.getComments() != null) {
comment.setComments(comment.getComments().replaceAll("<li>•", "<li>"));
}
return comment;
}
}
public class CommentBO {
public static CommentBO createNewComment(Integer clientNumber, Integer commentCategory) {
CommentBO bo = new CommentBO();
bo.setClientNumber(clientNumber);
bo.setCommentCategory(commentCategory);
return bo;
}
private Integer clientNumber;
private Integer commentCategory;
private String comments;
public Integer getClientNumber() {
return clientNumber;
}
public void setClientNumber(Integer clientNumber) {
this.clientNumber = clientNumber;
}
public Integer getCommentCategory() {
return commentCategory;
}
public void setCommentCategory(Integer commentCategory) {
this.commentCategory = commentCategory;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
}
public class ReflectionTestUtils {
public static void setField(Object object, String fieldName, Object value) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
}
catch(Exception e) {
throw new RuntimeException(e);
}
}
}
public class AssessmentServiceTest {
public AssessmentService assessmentService = new AssessmentServiceImpl();
@Test
public void testGetComment(){
Integer clientNumber = 1;
Integer commentCategory = 1;
CommentBO commentBO = CommentBO.createNewComment(clientNumber, commentCategory);
AssessmentDao assessmentDao = EasyMock.createMock(AssessmentDao.class);
expect(assessmentDao.getComment(anyObject(), anyObject())).andReturn(commentBO);
ReflectionTestUtils.setField(assessmentService, "assessmentDao", assessmentDao);
replay(assessmentDao);
CommentBO bo = assessmentService.getComment(clientNumber, commentCategory);
verify(assessmentDao);
assertThat(bo , instanceOf(CommentBO.class));
}
}