将通过现场注入(CDI)初始化的测试字段

时间:2017-06-22 00:19:49

标签: java jsf java-ee dependency-injection cdi

让我们假设我们已经将以下代码段作为完整Java EE应用程序的一部分:

@Singleton
public class LoginService {


  @Inject
  private UserDAO userDAO;



  protected boolean login(String username, String password){

   // [...]
   User user = userDAO.findByUsername(username);

  // [...]

  }


}

UserDAO是一个接口,该接口有一个名为DatabaseUserDAO的特定类实现,它被注入到userDAO字段中。

现在我要为登录方法e编写一个测试。 G。 testLoginSuccessfulIfLoginDataCorrect()。但由于我不想依赖于数据库,我只想通过使用一个类来存根它。 public class TestUserDAO implements UserDAO并注入此一个而不是注入的默认类。有什么可能实现它?我们还假设没有构造函数注入或其他方法来初始化字段。

2 个答案:

答案 0 :(得分:2)

使用arquillian(http://arquillian.org/)以及mockito(http://site.mockito.org/)或其衍生产品之一:

  • 创建一个UserDAO的模型来注入
  • 使用模拟
  • 从您正在测试的类中创建一个包
  • 创建一个junit测试,它将您的LoginService与注入的模拟一起使用,并可以将其用于测试:

示例(从实际代码修改为与您的类名有些匹配): (注意:这种部署生成仅适用于maven项目)

  <style type="text/css">
        .table {
            width: 310px;
        }

        td:nth-child(1) {
            width: 200px;
        }

        .table-responsive {
            border: 1px solid;
            width: 340px;
            padding: 20px 30px 10px 10px;
            border-radius: 5px;
        }

        td:nth-child(2),
        td:nth-child(3),
        td:nth-child(4) {
            width: 30px;
        }

        tr:active {
            color: orange;
        }

        td:hover {
            background-color: #00BD9A;
        }

    </style>

请注意,您需要以这种方式更改测试中的类,以便进行测试。

答案 1 :(得分:1)

嗯,这并不是秘密。

你有四种可能性。

  1. 为所有DAO(EJB)创建构造函数。

    @Singleton
    public class LoginService {
    
      @Inject
      private UserDAO userDAO;
    
      LoginService (UserDAO userDAO) {
         this.userDAO = userDAO;
      }
    
    }
    
  2. 为每个DAO创建一个集合。

    @Singleton
    public class LoginService {
    
      @Inject
      private UserDAO userDAO;
    
      setUserDAO(UserDAO userDAO) {
         this.userDAO = userDAO;
      }
    }
    
  3. 使用默认访问

    直接设置变量
    @Singleton
    public class LoginService {
    
      @Inject
      UserDAO userDAO;
    
    }
    

    在你的测试中:

    loginService.userDAO = userDAOMocked.
    
  4. 因此,您可以使用构造函数或setter模拟UserDAO并将其作为参数传递给LoginService测试。

    另一个是by reflection(没有构造函数或setter),但我不喜欢这种方法......:

    1. 反射

      public static void setPrivateField(Class<? extends Object> instanceFieldClass, Object instance, String fieldName, Object fieldValue) throws Exception {
          Field setId = instanceFieldClass.getDeclaredField(fieldName);
          setId.setAccessible(true);
          setId.set(instance, fieldValue);
      }
      

      使用:

      setPrivateField(loginService, "userDAO", userDAOMocked);