Я создал специальный 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;
}
}
Когда я выполняю свой тестовый метод, я получаю java.lang.NullPointerException
at com.medkhelifi.tutorials.todolist.models.dao.TodoDao.getTodosByUserId(TodoDao.java:30)
в строке 30 (как показано в классе TodoDao.java).
Не знаю, упустил ли я что-то.
Хорошо, я добавлю свою реализацию класса TodoDao.
Создайте Дао сами. Вы не вводите насмешки, вы записываете поведение. Итак, ваш TodoDao - это не фикция и не ваша сессионная фабрика. Так зачем усложнять ...
Вы не определили поведение своего макета sessionFactory
. Поэтому, когда ваш метод вызывает sessionFactory.getCurrentSession()
, он возвращает ноль, и это приводит к NullPointerException
.
Добавьте приведенный ниже код в свой тестовый метод getTodosByUserIdShouldNotReturnNull
или ваш метод setUp
, а также вам понадобится еще несколько фиктивных объектов:
when(sessionFactory.getCurrentSession()).thenReturn(sessionMock);
when(sessionMock.createQuery("from Todo where userId = ?")).thenReturn(queryMock);
Но поскольку мой SessionFactory уже автоматически подключен к настоящему bean-компоненту, он не предполагает, что у него уже есть собственный сеанс ??
Почему вы хотите, чтобы ваш sessionFactory
использовал настоящий bean-компонент для модульного тестирования? В модульном тестировании вы тестируете один конкретный класс и имитируете все остальные зависимые классы.
Я хочу использовать реальный компонент sessionFactory для тестирования с данными H2 (уже созданными в моих двух сценариях sql). Могу ли я сделать это только с фиктивными фиктивными бобами?
тогда это может быть проблема с вашим bean-компонентом sessionFactory, поскольку вы не хотите имитировать его.
У вас есть пример или руководство по тестированию с базой данных H2? В Google без результата
Проверьте это - это может помочь. baeldung.com/spring-jpa-test-in-memory-database
На какой строчке выкидывает NPE? Также вы можете опубликовать свою реализацию класса
TodoDao
?