【问题标题】:NullPointerException when using Mockito使用 Mockito 时出现 NullPointerException
【发布时间】:2011-12-15 23:27:23
【问题描述】:

我正在尝试使用 Mockito 创建一个测试,但是我得到了 NullPointerException。

以下是会话bean:

package edu.city.set.eia.citypress.beans;

import edu.city.set.eia.citypress.model.RegisUser;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;


@Stateless
public class RegisUserFacade extends AbstractFacade<RegisUser> implements RegisUserFacadeLocal {
    @PersistenceContext(unitName = "citypress_PU")
    private EntityManager em;

    @Override
    public EntityManager getEntityManager() {
        return em;
    }

    public void setEntityManager(EntityManager em) {
        this.em = em;
    }


    public RegisUserFacade() {
        super(RegisUser.class);
    }


    @Override
    public RegisUser findByUsername(String username) {
        Query query = this.getEntityManager().createQuery("select r from RegisUser r where username=:username");
        query.setParameter("username", username);
        RegisUser regisuser;
        try { 
            regisuser = (RegisUser) query.getSingleResult();
        }
        catch (Exception e){
            regisuser = null;
        }
        return regisuser;
    }

    @Override
    public RegisUser findByUserPass(String username, String password){
        Query query = this.getEntityManager().createNamedQuery("RegisUser.findByUserPass");
        query.setParameter("username", username);
        query.setParameter("password", password);
        RegisUser regisuser;

        try { // To prevent javax.persistence.NoResultException
            regisuser = (RegisUser) query.getSingleResult();
        }
        catch (Exception e){
            regisuser = null;
        }

        return regisuser;
    }

    @Override
    public RegisUser findByEmail(String email) {
        Query query = em.createQuery("select r from RegisUser r where r.email = :email");
        query.setParameter("email", email);
        RegisUser regisuser;
        try { 
            regisuser = (RegisUser) query.getSingleResult();
        }
        catch (Exception e){
            regisuser = null;
        }
        return regisuser;
    }
}

这是测试类:

package edu.city.set.eia.citypress.mocking.beans;

import edu.city.set.eia.citypress.beans.RegisUserFacade;
import edu.city.set.eia.citypress.model.RegisUser;
import javax.persistence.Query;
import javax.persistence.EntityManager;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class RegisUserTest {

  private final transient EntityManager mockedEm =
          mock(EntityManager.class);
  private final transient Query mockedQuery =
          mock(Query.class);
  private static final String EMAIL = "test_email";
  private static final String INVALID_EMAIL = "test_email_invalid";

  @Before
  public final void setUp() {

    when(mockedEm.createQuery("Select r from RegisUser r where "
            + "r.email = :email")).thenReturn(mockedQuery);

    when(mockedQuery.setParameter("email", EMAIL)).thenReturn(mockedQuery);
    when(mockedQuery.setParameter("email", INVALID_EMAIL)).thenReturn(mockedQuery);
  }

  @Test
  public void testValidEmail() throws Exception {

    final RegisUser expectedUser = new RegisUser();
    expectedUser.setEmail(EMAIL);

    when(mockedQuery.setParameter("email", EMAIL)).thenReturn(mockedQuery);
    when(mockedQuery.getSingleResult()).thenReturn(expectedUser);

    RegisUserFacade bean = new RegisUserFacade();
    bean.setEntityManager(mockedEm);
    RegisUser user = bean.findByEmail(EMAIL);
    assertNotNull(user);
    assertEquals(EMAIL, user.getEmail());
  }

  @Test(expected = Exception.class)
  public void testInValidEmail() throws Exception {
    final RegisUser expectedUser = new RegisUser();
    expectedUser.setEmail(EMAIL);


    when(mockedQuery.setParameter("email", INVALID_EMAIL)).thenReturn(mockedQuery);
    when(mockedQuery.getSingleResult()).thenThrow(new Exception());

    RegisUserFacade bean = new RegisUserFacade();
    bean.setEntityManager(mockedEm);
    bean.findByEmail(INVALID_EMAIL);
  }
}

我得到的错误是testValidEmail caused an ERROR: java.lang.NullPointerException

【问题讨论】:

  • 你在哪一行得到了异常?
  • 在 RegisUserFacade.findByEmail(RegisUserFacade.java:68) 和 RegisUserTest.testValidEmail(RegisUserTest.java:43)
  • 行号在没有提供代码时没有多大帮助...
  • 错误导致我告诉的行。此外,我已经包含了会话 bean,以便您可以检查代码。但是,问题太奇怪和奇怪了:/
  • 当我将您的 RegisUserFacade.java 复制并粘贴到 Eclipse 中时,第 68 行仅包含一个 }。是这样吗?你的第 68 行是什么?

标签: java mocking nullpointerexception mockito


【解决方案1】:

我不熟悉 Mockito,但看起来你的字符串不匹配。如果 Mockito 区分大小写,那么它可以解释为什么您的 query 对象是 null

when(mockedEm.createQuery("select r from RegisUser r where r.email = :email")).thenReturn(mockedQuery);

注意“select”中的小写“s”,它与您的 bean 中的内容相匹配。

【讨论】:

  • 小写的s??我没听懂你
  • 您的 bean 有“选择”,您的测试有“选择”。
  • @user1064580 太好了!接受这个答案会让我很开心:)
  • 我已经花了好几个小时了..!我真的不知道如何感谢你。此外,这是我的最后一个项目。所以我相信你能理解你的帮助。再次感谢你,你摇滚!
  • @user1064580 在我的回答中点击那个小复选标记是表达感谢的好方法:)
【解决方案2】:

我遇到了同样的问题,我认为这个问题更为根本。 mockedQuery.setParameter 方法应该就地修改 mockedQuery 而不是简单地返回一些东西。我使用 thenAnswer 方法而不是 thenReturn 方法解决了这个问题。

Mockito.when(mockedQuery.setParameter(anyString(), anyString())).then(
  new Answer<Query>() {
    public Query answer(InvocationOnMock invocation) {
      Object[] argumentsToTest = invocation.getArguments();
      if (!"email".equals((String) argumentsToTest[0])) {
        return findUserByIdQuery;
      }
      if (EMAIL.equals((String) argumentsToTest[1])) {
        Mockito.when(mockedQuery.getSingleResult()).thenReturn(expectedUser);
      } else {
        Mockito.when(mockedQuery.getSingleResult()).thenThrow(new Exception());
      }
      return mockedQuery;
    }
  }
);

这样您可以将整个模拟放入 @Before 块中,并将测试留给测试行为。希望这会有所帮助!

【讨论】:

    【解决方案3】:

    如果NullPointerException 被抛出query.setParameter("email", email);,那么query 就是null。也许您需要在该查询字符串中终止 ;

    【讨论】:

    • 如何在查询字符串中添加一个终止符?
    • 我的意思是“终止”,如“结束”,“终止 ; 在该查询字符串中”,如"select r from RegisUser r where r.email = :email;"
    • 试过了,不幸的是同样的错误:/一直说查询是空的,这很奇怪:/
    • query 对象被模拟,因此setParameter 方法是否接受null 值无关紧要。
    猜你喜欢
    • 2021-11-17
    • 2016-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多