【问题标题】:How to mock JPA for Post method using mockito如何使用 mockito 为 Post 方法模拟 JPA
【发布时间】:2018-02-27 09:08:38
【问题描述】:

我正在尝试为使用 JPA 作为 DAO 层的 Create(Post) 方法编写单元测试。我是 Mockito 的新手,因此需要洞察力。

1.EmployeeService .java
@Component("IEmployeeService ")
public class EmployeeService implements IInputService {
@Inject
EntityManagerFactory emf;

@PersistenceContext
EntityManager em;

public InputEntity create(InputEntity inputEntity) {
          em = emf.createEntityManager();
    try {
        em.getTransaction().begin();
        inputEntity.setLST_UPDTD_TS(new Date());
        inputEntity.setLST_UPDTD_USER_ID(new String("USER1"));
        em.persist(inputEntity);
        em.getTransaction().commit();  
    } catch (PersistenceException e)

    {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
        throw new  WebApplicationException(e,Response.Status.INTERNAL_SERVER_ERROR);
    }

    finally {
        em.close();
    }
    return inputEntity;
}

2.InputEntity.java 是 Entity 类,具有 getter 和 setter,用于对应列的员工年龄、薪水等。

现在,如果调用 Post 方法,将调用 EmployeeService 类中的 create 方法。我必须使用 mockito 编写一个单元测试,并且我得到空指针,下面是我编写的测试。

@Category(UnitTest.class)
@RunWith(MockitoJUnitRunner.class)
public class EmployeeServiceTest {
    @Before
    public void initMocks() {
        MockitoAnnotations.initMocks(this);
    }

    @Autowired
    EmployeeService employeeService;

    @Mock
    InputEntity inputEntity;

    @Mock
    EntityManagerFactory emf;

    @Mock
    private EntityManager em;

    @Mock
    private EntityTransaction et;

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Test
   public void test_create_employee_success() throws Exception {

    InputEntity expected = Mockito.mock(InputEntity .class);
    Mockito.when(em.getTransaction()).thenReturn(et);
    Mockito.when(emf.createEntityManager()).thenReturn(em);
    Mockito.doReturn(expected).when(employeeService).create(inputEntityMock);
    InputEntity actual = new InputEntity();     
    Mockito.doReturn(actual).when(employeeService).create(inputFileRoleValidationMock);
    assertEquals(expected, actual);

}

【问题讨论】:

    标签: spring rest jpa mockito


    【解决方案1】:

    你有一个本地模拟 expected,你试图在 assertEquals() 中使用它,但这永远不会起作用,因为 assertEquals 使用 Object.equals,而 Mockito 劫持 equals 供内部使用。 Mockito mock 永远不会 Object.equals 除了它自己之外的任何东西。

    【讨论】:

      【解决方案2】:

      我们遇到了类似的 NullPointerException 问题,这是因为实体管理器。在 setUp 方法中更新连接属性后,我们就可以调用 JPA。

      您可以尝试像这样设置连接属性。

          //declare emfactory 
          private static EntityManagerFactory emfactory;
          private static EntityManager em;
      
          @BeforeClass
          public static void setUp() throws Exception{
                 Map<Object, Object> properties = new HashMap<Object, Object>();
                 properties.put("openjpa.ConnectionURL", 
                        "jdbc:db2://yourserver:port/DBName");
                 properties.put("openjpa.ConnectionUserName", "username");
                 properties.put("openjpa.ConnectionPassword", "userpassword");
                 //set Schema
      
                 //set Driver Name
      
                 emfactory = Persistence.createEntityManagerFactory("PersistenceUnitName", 
                                    properties);
                 em = emfactory.createEntityManager();
                 Mockito.when(emf.createEntityManager()).thenReturn(em);
           }
      

      另外,您需要修改 test_create_employee_success() 以使其正常工作。您正在嘲笑此方法中的所有内容,您不应该这样做。你可以试试这样的。

          @Test
          public void test_create_employee_success() throws Exception {
          {
               InputEntity inputEntity = new InputEntity();
               employeeService.create(inputEntity);
          }
      

      【讨论】:

      • 感谢您的见解。我实际上是在 JPA 中使用 Spring Boot,因此在设置类中创建实体管理器仍然给我带来了问题。所以我尝试使用 @asg 模拟 DataSource 的方式,就像现在一样,从长远来看,我必须尝试测试你提到的真实来源。
      【解决方案3】:

      您需要对代码进行以下更改:

      1.代替

      @Autowired
      EmployeeService employeeService;
      

      你可以使用:

      @InjectMocks
      private EmployeeService EmployeeService;
      
      1. 同样,当您在方法中进行模拟时 - InputEntity expected = Mockito.mock(InputEntity .class);除非在其他方法中使用,否则您不需要在类级别进行此声明。

      2. 你也可以摆脱声明 -

        InputEntity 实际 = new InputEntity();

        您不能使用 new 关键字断言模拟对象和对象的相等性。

      干净的单元测试看起来像这样 -

      import javax.persistence.EntityManager;
      import javax.persistence.EntityManagerFactory;
      import javax.persistence.EntityTransaction;
      
      import org.junit.Test;
      import org.junit.runner.RunWith;
      import org.mockito.InjectMocks;
      import org.mockito.Mock;
      import org.mockito.Mockito;
      import org.mockito.runners.MockitoJUnitRunner;
      
      @RunWith(MockitoJUnitRunner.class)
      public class EmployeeServiceImplTest {
      
          @Mock
          private EntityManager em;
      
          @Mock
          private EntityManagerFactory emf;
      
          @InjectMocks
          private EmployeeService EmployeeService;
      
          @Mock
          private EntityTransaction et;
      
          @Test
          public void testCreate() throws Exception {
              InputEntity expected = Mockito.mock(InputEntity.class);
              Mockito.when(em.getTransaction()).thenReturn(et);
              Mockito.when(emf.createEntityManager()).thenReturn(em);
              EmployeeService.create(expected);
              Mockito.verify(em, Mockito.times(1)).persist(expected);
          }
      
      }
      

      【讨论】:

      • 它有效。欣赏你的见解,它干净简单,让我理解了这个概念
      猜你喜欢
      • 2020-12-08
      • 2012-02-29
      • 2020-03-20
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多