【问题标题】:JUnit Mockito @InjectMock an Autowired Sessionfactory BeanJUnit Mockito @InjectMock 一个自动装配的 Sessionfactory Bean
【发布时间】:2019-04-04 15:03:57
【问题描述】:

我创建了一个特殊的 applicationContext-test.xml 以将其用于我的测试类。

applicationContext-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

    <context:property-placeholder location="classpath:db/database.properties"/>
    <context:annotation-config />


    <!--        DATASOURCE                      -->
    <jdbc:embedded-database id="h2dataSource" type="H2">
        <jdbc:script location="classpath:db/sql/create-db.sql" />
        <jdbc:script location="classpath:db/sql/insert-data.sql" />
    </jdbc:embedded-database>

    <!-- SESSION FACTORY -->
    <bean id="testSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="h2dataSource"/>
        <property name="packagesToScan" value="com.medkhelifi.tutorials.todolist.models.entities"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect"> ${hibernate.dialect} </prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <!-- MUST have transaction manager, using aop and aspects  -->
    <bean id="testTransactionManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="testSessionFactory" />
    </bean>
    <tx:annotation-driven transaction-manager="testTransactionManager" />
</beans>

现在我想使用我的 testSessionFactory 作为 Autowired Bean 并将其注入到我的模拟中。

TodoDaoTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration (value = "classpath:/conf/applicationContext-test.xml")
public class TodoDaoTest {

    @Autowired
    @Mock
    SessionFactory testSessionFactory;

    @InjectMocks
    TodoDao todoDao;


    private boolean mockInitialized = false;

    @Before
    public void setUp(){
        if(!mockInitialized) {
            MockitoAnnotations.initMocks(this);
            mockInitialized = true;
        }    
    }

    @Test
    public void getTodosByUserIdShouldNotReturnNull(){
        User user = new User();
        assertNotNull(todoDao.getTodosByUserId(user.getId()));
    }
}

这是我的 TodoDao 课程 TodoDao.java

@Component
@Transactional
public class TodoDao implements ITodoDao {

    @Autowired
    private SessionFactory sessionFactory;

    @Autowired
    private AuthenticationFacade authenticationFacade;

    @Override
    @PostFilter("filterObject.userByUserId == authenticationFacade.getAuthenticatedFacade()")
    public List<Todo> getTodosByUserId(int userId) {
        List todos;
        // this is line 30
        todos = sessionFactory.getCurrentSession().createQuery("from Todo where userId = ?").setParameter(0, userId).list(); // this is line 30
        return todos;
    }
}

当我执行我的测试方法时,我在第 30 行得到一个java.lang.NullPointerException at com.medkhelifi.tutorials.todolist.models.dao.TodoDao.getTodosByUserId(TodoDao.java:30)(如 TodoDao.java 类所示) 我不知道我是否错过了什么。

【问题讨论】:

  • 在哪一行抛出 NPE?您也可以发布您的TodoDao 类实现吗?
  • 好的,我将添加我的 TodoDao 类实现。
  • 自己创建道。你不会注入你记录行为的模拟。因此,您的“TodoDao”既不是模拟也不是您的会话工厂。那么为什么要让它更复杂......

标签: java spring junit mockito autowired


【解决方案1】:

您尚未定义 sessionFactory 模拟的行为。因此,当您的方法调用 sessionFactory.getCurrentSession() 时,它会返回 null,这会导致 NullPointerException

在您的测试方法getTodosByUserIdShouldNotReturnNull 或您的setUp 方法中添加以下代码,并且您将需要更多的模拟对象:

when(sessionFactory.getCurrentSession()).thenReturn(sessionMock); when(sessionMock.createQuery("from Todo where userId = ?")).thenReturn(queryMock);

【讨论】:

  • 但是由于我的 SessionFactory 已经从一个真正的 bean 自动装配,它不应该已经创建了自己的会话??
  • 您为什么希望您的sessionFactory 使用真正的bean 进行单元测试?在单元测试中,您测试一个特定的类并模拟所有其他依赖类
  • 我想使用真正的 sessionFactory Bean 来测试 H2 数据(已经在我的两个 sql 脚本中创建)。我可以只用虚构的模拟豆子来做吗?
  • 那么这可能是您的 sessionFactory bean 的问题,因为您不想模拟它。
  • 您有如何使用 H2 数据进行测试的示例或教程吗?我用谷歌搜索没有得到任何结果
猜你喜欢
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多