Модульное тестирование

 
 
 
Сообщения:7
Здравствуйте
Имеется интерфейс для сервисов реализующих Crud операции:

/**
 * 
 * @param <T> - managed class primary key
 * @param <T> - managed class type
 */
public interface CrudService<K,T> {
	/**
	 * @param primaryKey
	 * @return newly created object if doesnt exited before, or null(if existed before)
	 */
	public @Nullable T create(@Nonnull K primaryKey);
	/**
	 * @param primaryKey
	 * @return object which were created earlier or null
	 */
	public @Nullable T read(@Nonnull K primaryKey);
	/**
	 * @param object
	 * @return true if object was successfully updated
	 */
	public boolean update(@Nonnull T object);
	/**
	 * @param primaryKey
	 * @return true if object was successfully deleted
	 */
	public boolean delete(@Nonnull K primaryKey);
	
}


Имеется его реализация AccountService, предоставляющая доступ к CRUD операциям над объектами класса Account:
public class AccountsCrudService implements CrudService<String, Account> {

	private final AccountsDAO dao; //DAO object implementation for managing accounts
	
	public AccountsCrudService(AccountsDAO dao) {
		this.dao = dao;
	}
	
	@Override
	public Account create(String primaryKey) {
		Account account = Account.newAccount(primaryKey);
		if(dao.insert(account))
			return account;
		else
			return null;
	}

	@Override
	public Account read(String primaryKey) {
		Account account = dao.load(primaryKey);
		return account;
	}

	@Override
	public boolean update(Account account) {
		return dao.update(account);
	}

	@Override
	public boolean delete(String primaryKey) {
		return dao.delete(primaryKey);
	}
}


AccountsDAO - DAO интерфейс для CRUD операций с аккаунтами в базе данных. В реальном приложении, для получения реализации этого интерфейса работающего с базой данных, необходимо предварительно проинициализировать базу данных.

Я правильно понимаю, для модульного теста AccountsCrudService мне необходимо написать "заглушку" для этого интерфейса(которая например вместо базы будет сохранять/читать в HashMap)?

Что даст создание такого теста, ведь в реальном приложении у нас будет использоваться другая реализация DAO объекта?

Простите за нубские вопросы, прочитал всё что смог найти, но понимание принципов тестирования не пришло =( Пытаюсь прийти к пониманию через опыт
Буду также рад комментариям по улучшению кода, если таковые имеются
Изменен:19 июн 2018 11:08
 
 
Сообщения:9691
Nomre:
Я правильно понимаю, для модульного теста AccountsCrudService мне необходимо написать "заглушку" для этого интерфейса(которая например вместо базы будет сохранять/читать в HashMap)?
Да, но можно написать немодульный тест. Часто для эмуляции настоящей БД используют in-memory базы (к примеру, H2).
Nomre:
Что даст создание такого теста, ведь в реальном приложении у нас будет использоваться другая реализация DAO объекта?
Ну если в сервисе оч много логики, то это даст возможность написать много модульных тестов. Если же там логики мало, то и заглушка не очень оправдана - можно написать несколько компонентных тестов.
Изменен:19 июн 2018 11:34
 
 
Сообщения:7
Староверъ:
Да, но можно написать немодульный тест. Часто для эмуляции настоящей БД используют in-memory базы (к примеру, H2).

Спасибо, действительно, in-memory база наверное будет лучшим вариантом, хотя бы с точки зрения проверки валидности запросов.

А не подскажите как лучше организовать расположение тестовых файлов? В проекте исходники лежат в ./src/main/java, тесты в ./src/test/java. Тесты должны лежать в пакетах с такими же названиями, как тестируемые классы, или есть какая то более удобная логика расположения тестов?
Заглушку для AccountsDAO создавать в пакете с тем же названием, что и реальный AccountsDAO ?

Староверъ:
Ну если в сервисе оч много логики, то это даст возможность написать много модульных тестов. Если же там логики мало, то и заглушка не очень оправдана - можно написать несколько компонентных тестов.

Много модульных тестов - для чего? Один тест - одна проверяемая функция?
 
 
Сообщения:9691
Nomre:
А не подскажите как лучше организовать расположение тестовых файлов? В проекте исходники лежат в ./src/main/java, тесты в ./src/test/java. Тесты должны лежать в пакетах с такими же названиями, как тестируемые классы, или есть какая то более удобная логика расположения тестов?
Как правило их складывают в те же пакеты в src/test/java.
Nomre:
Заглушку для AccountsDAO создавать в пакете с тем же названием, что и реальный AccountsDAO ?
Эт не сильно важно. Наверно AccountsDAOMock будет понятней всего.
Nomre:
Много модульных тестов - для чего? Один тест - одна проверяемая функция?
Ну чтоб покрыть все возможные сценарии, все условия и циклы, вычисления и пр.
 
 
Сообщения:7
Староверъ, спасибо за разъяснения!

Подскажите, а если нескольким тест кейсам для работы нужен какой то внешний класс, который дорого инициализировать(пул соединений с базой данных например), его можно как то проинициализировать один раз и использовать во всех тест кейсах?
 
 
Сообщения:9691
Если в качестве DI использовать Spring IoC, то он сам знает что контексты нужно кешировать между тестами.
 
 
Сообщения:7
Староверъ:
Если в качестве DI использовать Spring IoC, то он сам знает что контексты нужно кешировать между тестами.

А если DI не используется?
 
 
Сообщения:9691
Значит самому прийдется придумывать кеширование или singleton'ы.
 
 
Сообщения:7
Староверъ:
Значит самому прийдется придумывать кеширование или singleton'ы.

Каким образом? Разве после выполнения первого теста, созданный им контекст не уничтожается? Я думал что тесты - это нечто вроде набора программ с main методом где то внутри JUnit, и всё что они создают не может передаваться от одного теста к другому.
 
 
Сообщения:9691
В любом случае в одном модуле все тесты бегут по умолчанию в одной JVM. Соответственно можно использовать статические фабрики и синглтоны для того чтоб шарить состояние.
 
 
Сообщения:7
А если модулей несколько? В каком из них инициализировать общий ресурс? Смотрел лекции технопарка Mail.RU про тестирование, там говорилось что результат выполнения тестов не должен зависеть от порядка их запуска
 
 
Сообщения:9691
Nomre:
А если модулей несколько?
Я говорил про Мавен модули. Если их много, то в каждом будет своя JVM и ресурсы нужно будет инициализировать заново.
Nomre:
Смотрел лекции технопарка Mail.RU про тестирование, там говорилось что результат выполнения тестов не должен зависеть от порядка их запуска
Правильно говорилось. Не знаю как это относится к текущему вопросу, правда.
Изменен:21 июн 2018 08:31
 
 
Сообщения:7
Староверъ:
Nomre:
А если модулей несколько?
Я говорил про Мавен модули. Если их много, то в каждом будет своя JVM и ресурсы нужно будет инициализировать заново.
Nomre:
Смотрел лекции технопарка Mail.RU про тестирование, там говорилось что результат выполнения тестов не должен зависеть от порядка их запуска
Правильно говорилось. Не знаю как это относится к текущему вопросу, правда.


А, я понял. Т.е. в рамках одного модуля ресурсы можно инициализировать один раз?
Тогда остаётся вопрос - каким образом это лучше делать так, чтобы они инициализировались перед запусками тестов? Чтобы от порядка запуска тестов не зависел результат
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет