如果你将Car类的第一个例子同使用setter依赖注入的例子进行比较,你可能认为后者使用了额外的步骤来实现Car类的依赖注入。这没错,你必须实现一个setter方法。但是当你在做单元测试的时候,你会感觉到这些额外的工作都是值得的。如果你对单元测试不熟悉,推荐你看一下这个帖子单元测试有毒 。我们的Car的例子太简单了,并没有把依赖注入对单元测试的重要性体现的很好。因此我们不再使用这个例子,我们使用前面已经讲述过的关于篝火故事的例子,特别是在在单元测试中使用mock中的部分。我们有一个servlet类,通过使用远端EJB来在农场中”注册”动物:
1 public class FarmServlet extends ActionServlet { 2 3 public void doAction( ServletData servletData ) throws Exception { 4 5 String species = servletData.getParameter("species"); 6 7 String buildingID = servletData.getParameter("buildingID"); 8 9 if ( Str.usable( species ) && Str.usable( buildingID ) ) { 10 11 FarmEJBRemote remote = FarmEJBUtil.getHome().create(); 12 13 remote.addAnimal( species , buildingID ); 14 15 } 16 17 } 18 19 } |
你已经注意到了FarmServlet被紧耦合到了FarmEJBRemote实例中,通过调用“FarmEJBUtil.getHome().create()”来取回实例值。这么做会非常难做单元测试。当作单元测试的时候,我们不想使用任何数据库。我们也不想访问EJB服务器。因为这不仅会使单元测试很难进行而且会使其变慢。所以为了能够顺利的为FarmServlet类做单元测试,最好使其变成松耦合的。为了清除FarmServlet和FarmEJBRemote之间的紧依赖关系,我们可以使用基于setter的依赖注入:
1 public class FarmServlet extends ActionServlet { 2 3 private FarmEJBRemote remote; 4 5 public void setRemote(FarmEJBRemote remote) { 6 7 this.remote = remote; 8 9 } 10 11 public void doAction( ServletData servletData ) throws Exception { 12 13 String species = servletData.getParameter("species"); 14 15 String buildingID = servletData.getParameter("buildingID"); 16 17 if ( Str.usable( species ) && Str.usable( buildingID ) ) { 18 19 remote.addAnimal( species , buildingID ); 20 21 } 22 23 } 24 25 } |
在真实的部署包中,我们确保通过调用“FarmEJBUtil.getHome().create()”而创建的一个FarmServlet远端成员实例会被注入。在我们的单元测试中,我们使用一个虚拟的mock类来模拟FarmEJBRemote。换句话说,我们通过使用mock类来实现FarmEJBRemote:
1 class MockFarmEJBRemote implements FarmEJBRemote { 2 3 private String species = null; 4 5 private String buildingID = null; 6 7 private int nbCalls = 0; 8 9 public void addAnimal( String species , String buildingID ) 10 11 { 12 13 this.species = species ; 14 15 this.buildingID = buildingID ; 16 17 this.nbCalls++; 18 19 } 20 21 public String getSpecies() { 22 23 return species; 24 25 } 26 27 public String getBuildingID() { 28 29 return buildingID; 30 31 } 32 33 public int getNbCalls() { 34 35 return nbCalls; 36 37 } 38 39 } 40 41 42 43 public class TestFarmServlet extends TestCase { 44 45 public void testAddAnimal() throws Exception { 46 47 // Our mock acting like a FarmEJBRemote 48 49 MockFarmEJBRemote mockRemote = new MockFarmEJBRemote(); 50 51 // Our servlet. We set our mock to its remote dependency 52 53 FarmServlet servlet = new FarmServlet(); 54 55 servlet.setRemote(mockRemote); 56 57 58 59 // just another mock acting like a ServletData 60 61 MockServletData mockServletData = new MockServletData(); 62 63 mockServletData.getParameter_returns.put("species","dog"); 64 65 mockServletData.getParameter_returns.put("buildingID","27"); 66 67 68 69 servlet.doAction( mockServletData ); 70 71 assertEquals( 1 , mockRemote.getNbCalls() ); 72 73 assertEquals( "dog" , mockRemote.getSpecies() ); 74 75 assertEquals( 27 , mockRemote.getBuildingID() ); 76 77 } 78 79 } |
这样很容易就能测试FarmServlet了。
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。