【问题标题】:Junit mockito when(..).thenReturn() throws NullPointerExceptionJunit mockito when(..).thenReturn() 抛出 NullPointerException
【发布时间】:2012-08-15 12:52:49
【问题描述】:

谁能解释一下下面的场景
要测试的代码
UserTransaction.java

@Override
public ServiceResponse<User> get(String name) {
    ServiceResponse<User> response = new ServiceResponse<User>();
    List<Map<String, Object>> exp = new ArrayList<Map<String, Object>>();
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("expression", "eq");
    map.put("property", "name");
    map.put("value", name);
    exp.add(map);
    List<User> users = userDao.getByCriteria(exp);
    if (!users.isEmpty()) {
        response.setResponse(users.get(0));
    } else {
        response.setResponse(null);
    }
    return response;
}   

UserDao.java

public List<User> getByCriteria(List<Map<String, Object>> exp) {
  DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
  for (Integer i=0;i<exp.size();i++){
    String expression = (String) exp.get(i).get("expression");
    String property = (String) exp.get(i).get("property");
    if(expression.equals("eq"){
       criteria.add(Restrictions.eq(property,exp.get(i).get("value")));
    }
  }
  return hibernateTemplate.findByCriteria(criteria);
 }

UserTransactionTest.java

private UserTransaction userTransactions = new UserTransaction();
private UserDao userDao = mock(UserDao.class);

@Test
public void testGet() {
   User user = new User();
   user.setName("Raman");
    try {
        when(userDao.getByCriteria(anyList())).thenReturn(user);
    } catch (Exception e) {
        e.printStackTrace();
    }
    ServiceResponse<User> response = userTransactions.get("raman");
    User result = response.getResponse();
    assertEquals("Raman", result.getName());
    assertEquals(0, response.getErrors().size());
}

工作正常。

但是我传递了一个用户定义的列表“myList”而不是“anyList()”

List<Map<String,Object>> myList = new ArrayList<Map<String,Object>>();
Map<String,Object> map = new HashMap<String,Object>();
map.put("expression","eq");
map.put("property","name");
map.put("value","raman");
myList.add(map);
when(userTransactions.getByCriteria(myList)).thenReturn(user);

assertEquals() 行抛出NullPointerException。为什么?如果给出anyList(),实际会发生什么?

【问题讨论】:

  • 您没有发布足够多的代码,导致其他人很难看到您哪里出错了。 when(userTransactions. 是拼写错误吗? myList 是如何创建的? getByCriteria() 的方法签名是什么?
  • 我在这里遗漏了什么吗?您继续发布when(userTransactions... 并且该对象尚未创建。您在上面的代码中创建了userTransaction,但没有创建userTransactions(注意末尾的“s”)。如果您调试代码,是否存在名为 userTransactions 的对象并且它是一个模拟对象?
  • 您能否澄清它是在when 的行上抛出异常,还是在实际调用getByCriteria 的测试行上抛出异常?并发布更多代码 - 正如其他人所说,您还没有真正提供足够的信息来让我们能够诊断出问题所在。

标签: java unit-testing junit mockito


【解决方案1】:

我确定您现在已经解决了您的问题,但如果有人偶然发现同样的问题,答案如下:

在您提供的代码中,您没有使用您创建的模拟 myListget() 方法总是调用局部变量 userDao.getByCriteria(exp)

这就是anyList() 有效,而myList 无效的原因。

如果您确实想要测试表达式,List&lt;Map&lt;String,Object&gt;&gt; exp 应该是您的类的成员,而不是局部变量:

public class UserTransaction {
    private List<Map<String,Object>> exp;

    public UserTransaction() {
        // creating a default exp value
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("expression", "eq");
        map.put("property", "name");
        map.put("value", name);
        exp.add(map);
    }

    // getters and setters for exp

    public ServiceResponse<User> get(String name) {
        ServiceResponse<User> response = new ServiceResponse<User>();
        List<User> users = userDao.getByCriteria(exp);
        if (!users.isEmpty()) {
            response.setResponse(users.get(0));
        } else {
            response.setResponse(null);
        }
        return response;
    }
}

在你的测试中:

private UserTransaction userTransactions = new UserTransaction();
private UserDao userDao = mock(UserDao.class);

@Test
public void testGet() {
    User user = new User();
    user.setName("Raman");

    // creating a custom expression
    List<Map<String,Object>> myList = new ArrayList<Map<String,Object>>();
    Map<String,Object> map = new HashMap<String,Object>();
    map.put("expression","eq");
    map.put("property","name");
    map.put("value","raman");
    myList.add(map);

    // replacing exp with the list created
    userTransactions.setExp(myList);
    // return user when calling getByCriteria(myList)
    when(userDao.getByCriteria(myList)).thenReturn(user);

    ServiceResponse<User> response = userTransactions.get("raman");
    User result = response.getResponse();
    assertEquals("Raman", result.getName());
    assertEquals(0, response.getErrors().size());
}

【讨论】:

    【解决方案2】:

    如果您的代码是完整的(我怀疑它可能不完整),那么您还没有指定包含 get() 方法的模拟对象。这应该出现在对when(...)的调用中

    我期待这样的代码......

    UserDao mockDao = mock(UserDao.class);
    
    when(mockDao.get(list)).thenReturn(users);
    

    【讨论】:

    • 我已经按照上面的做了。但问题是,当我将 anyList() 作为参数传递时,测试通过了,但是当我传递用户定义的“列表”时,它会抛出异常。
    【解决方案3】:

    我认为 anyList() 是一个你正在模拟的方法,而 list 不是一个方法,你能发布你正在编写这个测试用例的源代码吗

    【讨论】:

    • anyList() 是 Mockito 中的匹配器方法。
    【解决方案4】:

    首先,您不是在测试 UserDao。

    接下来,anyList() 生成 mockito 匹配器,您应该将 matcher 传递给 userDao.getByCriteria 以执行某些操作,因此,您应该使用 Matchers.same(your list) 或 Matchers.eq(your list)。

    出现异常是因为默认情况下 Mockito 创建了不错的模拟,并且默认情况下它们在任何意外的方法调用时返回 null。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-21
      • 2020-09-11
      • 2020-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-18
      • 1970-01-01
      相关资源
      最近更新 更多