Java EE单元测试笔记
来源:互联网 发布:网站域名和空间 编辑:程序博客网 时间:2024/05/25 21:34
1. 单元测试
1.1 测试对象。
1) OracleResource 是一个 Enterprise JavaBeans (EJB) 3.1 bean,用(REST) 来公开他的预言。
@Path("javafuture")@Statelesspublic class OracleResource { @Inject Instance<Consultant> company; @Inject Event<Result> eventListener; @GET @Produces(MediaType.TEXT_PLAIN) public String predictFutureOfJava(){ checkConsultantAvailability(); Consultant consultant = getConsultant(); Result prediction = consultant.predictFutureOfJava(); eventListener.fire(prediction); if(JAVA_IS_DEAD.equals(prediction)){ throw new IllegalStateException("Please perform a sanity / reality check"); } return prediction.name(); } void checkConsultantAvailability(){ if(company.isUnsatisfied()){ throw new IllegalStateException("No consultant to ask!"); } } Consultant getConsultant(){ for (Consultant consultant : company) { return consultant; } return null; }}2) Consultant 是一个 Java 接口, Blogger是一个实现。
public class Blogger implements Consultant{ @Override public Result predictFutureOfJava() { return Result.JAVA_IS_DEAD; }}3) PredictionAudit 也是EJB 3.1 bean,保存所有成功的和失败的预言。
@Statelesspublic class PredictionAudit { @PersistenceContext EntityManager em; public void onSuccessfulPrediction(@Observes(during= TransactionPhase.AFTER_SUCCESS) Result result){ persistDecision(result,true); } public void onFailedPrediction(@Observes(during= TransactionPhase.AFTER_FAILURE) Result result){ persistDecision(result,false); } void persistDecision(Result result,boolean success) { Prediction prediction = new Prediction(result,success); em.persist(prediction); } public List<Prediction> allDecisions(){ return this.em.createNamedQuery(Prediction.findAll).getResultList(); }}4)Prediction是JPA 2 实体。
@Entity@XmlRootElement@XmlAccessorType(XmlAccessType.FIELD)@NamedQuery(name=Prediction.findAll,query="Select d from Prediction d")public class Prediction { public final static String PREFIX = "com.abien.testing.oracle.entity.Prediction."; public final static String findAll = PREFIX + "findAll"; @Id @GeneratedValue @XmlTransient private long id; @Column(name="prediction_result") @Enumerated(EnumType.STRING) private Result result; @Temporal(TemporalType.TIME) private Date predictionDate; private boolean success; public Prediction() { this.predictionDate = new Date(); } public Prediction(Result result, boolean success) { this(); this.result = result; this.success = success; }//bookkeeping methods omitted}1.2 单元测试。
1) 选用Mockito来“模拟”各种难以实现的类、资源或服务,原理是它能够从类或接口创建“智能代理”(也称为模拟)
2) 要精确测试 PredictionAudit 类,必须“模拟”EntityManager。之后测试 EntityManager#persist 方法是否接收正确参数,但这里我们不测试是否真正保存 Prediction 实体。
import static org.mockito.Mockito.*;public class PredictionAuditTest { private PredictionAudit cut; @Before public void initializeDependencies(){ cut = new PredictionAudit(); cut.em = mock(EntityManager.class); } @Test public void savingSuccessfulPrediction(){ final Result expectedResult = Result.BRIGHT; Prediction expected = new Prediction(expectedResult, true); this.cut.onSuccessfulPrediction(expectedResult); verify(cut.em,times(1)).persist(expected); } @Test public void savingRolledBackPrediction(){ final Result expectedResult = Result.BRIGHT; Prediction expected = new Prediction(expectedResult, false); this.cut.onFailedPrediction(expectedResult); verify(cut.em,times(1)).persist(expected); }}3)精确测试OracleResource类,需要模拟 javax.enterprise.event.Event 和 javax.enterprise.inject.Instance。
public class OracleResourceTest { private OracleResource cut; @Before public void initializeDependencies(){ this.cut = new OracleResource(); this.cut.company = mock(Instance.class); this.cut.eventListener = mock(Event.class); }如果未找到 Consultant 实现,我们希望生成 IllegalStateException。
@Test(expected=IllegalStateException.class) public void checkConsultantAvailabilityWithoutConsultant(){ when(this.cut.company.isUnsatisfied()).thenReturn(true); this.cut.checkConsultantAvailability(); }模拟 javax.enterprise.inject.Instance 返回的 Iterator:
Iterator mockIterator(Consultant consultant) { Iterator iterator = mock(Iterator.class); when(iterator.next()).thenReturn(consultant); when(iterator.hasNext()).thenReturn(true); return iterator; }
通过上面的Iterator,枚举到Consultant 接口的 Blogger 实现则会返回 JAVA_IS_DEAD,这将引发 IllegalStateException。
@Test(expected=IllegalStateException.class) public void unreasonablePrediction(){ Consultant consultant = new Blogger(); Iterator iterator = mockIterator(consultant); when(this.cut.company.iterator()).thenReturn(iterator); this.cut.predictFutureOfJava(); }模拟 Event 实例,验证方法调用。
@Test public void unreasonablePredictionFiresEvent(){ Consultant consultant = new Blogger(); Result expectedResultToFire = consultant.predictFutureOfJava(); Iterator iterator = mockIterator(consultant); when(this.cut.company.iterator()).thenReturn(iterator); try{ this.cut.predictFutureOfJava(); }catch(IllegalStateException e){} verify(this.cut.eventListener,times(1)).fire(expectedResultToFire); }下面PredictionArchiveResource 使用了直接注入的 PredictionAudit 类。
@Path("predictions")@Statelesspublic class PredictionArchiveResource { @EJB PredictionAudit audit; @GET @Produces(MediaType.APPLICATION_JSON) public List<Prediction> allPredictions(@DefaultValue("5") @QueryParam("max") int max) { List<Prediction> allPredictions = audit.allPredictions(); if (allPredictions.size() <= max) { return allPredictions; } else { return allPredictions.subList(0, max); } }}尽管 PredictionAudit 是一个类而不是一个接口,但也可以轻松地模拟它。为了测试返回列表的大小限制,对 PredictionAudit 类进行了全面模拟
public class PredictionArchiveResourceTest { PredictionArchiveResource cut; @Before public void initialize(){ this.cut = new PredictionArchiveResource(); this.cut.audit = mock(PredictionAudit.class); } @Test public void allDecisionsWithMaxLesserReturn() throws Exception { int expectedSize = 2; List<Prediction> prediction = createDecisions(expectedSize); when(this.cut.audit.allPredictions()).thenReturn(prediction); List<Prediction> allDecisions = this.cut.allPredictions(3); assertThat(allDecisions.size(), is(expectedSize)); } @Test public void allDecisionsWithMaxGreaterReturn() throws Exception { int max = 5; int expected = 3; List<Prediction> prediction = createDecisions(max); when(this.cut.audit.allPredictions()).thenReturn(prediction); List<Prediction> allDecisions = this.cut.allPredictions(expected); assertThat(allDecisions.size(), is(expected)); } @Test public void allDecisionsWithMaxEqualReturn() throws Exception { //obvious code omitted } List<Prediction> createDecisions(final int nr) { return new ArrayList<Prediction>(){{ for (int i = 0; i < nr; i++) { add(new Prediction(Result.BRIGHT, true)); } }}; }}
原帖(http://www.oracle.com/technetwork/cn/articles/java/unittesting-455385-zhs.html)
原帖代码:https://kenai.com/projects/javaee-patterns/sources/hg/show/TestingEJBAndCDI
0 0
- Java EE单元测试笔记
- JAVA EE课堂笔记
- Java EE学习笔记
- Java EE笔记一
- Java EE笔记二
- Java EE 笔记三
- Java EE 学习笔记
- Java EE学习笔记
- Java EE AWT笔记01
- Java EE 的一点笔记
- Java EE 学习笔记 I——Java EE 概述
- Java EE编程技术学习笔记(1)-Java EE概述
- 学习笔记-轻量级Java EE:JSP基本知识
- 学习笔记-轻量级Java EE:Servlet基础
- Java EE 7 Servlet3.0学习笔记
- java EE 笔记2
- java ee web开发学习笔记
- Java EE V7.0学习笔记:JPA
- ActionScript 3.0 为什么不支持函数重载
- 深入浅出 MFC Dynamic Creation 动态创建
- android学习之五·使用系统组件TabHost(使用布局文件)
- 编程小练习(4)
- 线程池任务队列
- Java EE单元测试笔记
- 重量级和轻量级(转)
- UVA 10795 <递归>
- 机房收费系统重构之设计
- Vim 常用插件和键位映射配置
- RHEL/CentOS 7.x如何启动/关闭、启用/禁用服务? 修改系统运行级别
- No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案
- Vim神级插件: EasyMotion
- 31CentOS7开机启动管理systemd简介及使用