依赖注入和单元测试

发表于:2018-6-21 09:28

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Edison Chou    来源:博客园

  如果你将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),我们将立即处理。
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号