Статьи

Тестирование приложений Spring Data MongoDB с NoSQLUnit

Spring Data MongoDB — это проект в рамках проекта Spring Data, который предоставляет расширение модели программирования Spring для написания приложений, использующих MongoDB в качестве базы данных.

Чтобы писать тесты с использованием NoSQLUnit для приложений Spring Data MongoDB , вам не нужно ничего особенного, кроме того, что Spring Data MongoDB использует специальное свойство _class для хранения информации о типе вместе с документом.

_class хранит полное имя класса внутри документа для документа верхнего уровня, а также для каждого значения, если оно является сложным типом.

Тип сопоставления

MappingMongoConverter используется в качестве реализации сопоставления типов по умолчанию, но вы можете настроить еще больше, используя @TypeAlias или реализацию интерфейса TypeInformationMapper .

заявка

Звездный Флот попросил нас разработать приложение для хранения всех журналов членов экипажа корабля в их системах. Для реализации этого требования мы будем использовать базу данных MongoDB в качестве бэкэнд-системы и Spring Data MongoDB на уровне персистентности.
Лог- документы имеют следующий формат json :

Пример документа журнала

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
{
        "_class" : "com.lordofthejars.nosqlunit.springdata.mongodb.log.Log" ,
        "_id" : 1 ,
        "owner" : "Captain" ,
        "stardate" : {
                "century" : 4 ,
                "season" : 3 ,
                "sequence" : 125 ,
                "day" : 8
        } ,
        "messages" : [
                        "We have entered a spectacular binary star system in the Kavis Alpha sector on a most critical mission of astrophysical research. Our eminent guest, Dr. Paul Stubbs, will attempt to study the decay of neutronium expelled at relativistic speeds from a massive stellar explosion which will occur here in a matter of hours." ,
                        "Our computer core has clearly been tampered with and yet there is no sign of a breach of security on board. We have engines back and will attempt to complete our mission. But without a reliable computer, Dr. Stubbs' experiment is in serious jeopardy."
        ]
}

Этот документ смоделирован на два Java- класса, один для всего документа и другой для обычной части.

Звездный класс

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Document
public class Stardate {
 
        private int century;
        private int season;
        private int sequence;
        private int day;
 
        public static final Stardate createStardate(int century, int season, int sequence, int day) {
 
                Stardate stardate = new Stardate();
 
                stardate.setCentury(century);
                stardate.setSeason(season);
                stardate.setSequence(sequence);
                stardate.setDay(day);
 
                return stardate;
 
        }
 
        //Getters and Setters
}

Лог класс

01
02
03
04
05
06
07
08
09
10
11
12
13
@Document
public class Log {
 
        @Id
        private int logId;
 
        private String owner;
        private Stardate stardate;
 
        private List<String> messages = new ArrayList<String>();
 
        //Getters and Setters
}

Помимо классов моделей нам также необходим класс DAO для реализации операций CRUD и файл контекста приложения Spring .

Класс MongoLogManager

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
@Repository
public class MongoLogManager implements LogManager {
 
        private MongoTemplate mongoTemplate;
 
        public void create(Log log) {
                this.mongoTemplate.insert(log);
        }
 
        public List<Log> findAll() {
                return this.mongoTemplate.findAll(Log.class);
        }
 
        @Autowired
        public void setMongoTemplate(MongoTemplate mongoTemplate) {
                this.mongoTemplate = mongoTemplate;
        }
 
}

файл контекста приложения

01
02
03
04
05
06
07
08
09
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
 
     <context:component-scan base-package="com.lordofthejars.nosqlunit.springdata.mongodb"/>
     <context:annotation-config/>
 
</beans>

В этом примере мы использовали класс MongoTemplate для доступа к MongoDB, чтобы не создавать слишком сложный пример, но в более CrudRepository проекте я рекомендую использовать подход Spring Data Repository путем реализации интерфейса CrudRepository в классах менеджера.

тестирование

Как было сказано ранее, вам не нужно делать ничего особенного, кроме правильного использования свойства class . Давайте посмотрим на набор данных, используемый для тестирования метода findAll, заполнив коллекцию _log базы данных журналов .

файл всех журналов

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
        "log":[
                {
                        "_class" : "com.lordofthejars.nosqlunit.springdata.mongodb.log.Log" ,
                        "_id" : 1 ,
                        "owner" : "Captain" ,
                        "stardate" : {
                                "century" : 4 ,
                                "season" : 3 ,
                                "sequence" : 125 ,
                                "day" : 8
                        } ,
                        "messages" : [
                                "We have entered a spectacular binary star system in the Kavis Alpha sector on a most critical mission of astrophysical research. Our eminent guest, Dr. Paul Stubbs, will attempt to study the decay of neutronium expelled at relativistic speeds from a massive stellar explosion which will occur here in a matter of hours." ,
                                "Our computer core has clearly been tampered with and yet there is no sign of a breach of security on board. We have engines back and will attempt to complete our mission. But without a reliable computer, Dr. Stubbs' experiment is in serious jeopardy."
                        ]
                }
                ,
                {
                        "_class" : "com.lordofthejars.nosqlunit.springdata.mongodb.log.Log" ,
                        "_id" : 2 ,
                        "owner" : "Captain" ,
                        "stardate" : {
                                "century" : 4 ,
                                "season" : 3 ,
                                "sequence" : 152 ,
                                "day" : 4
                        } ,
                        "messages" : [
                                "We are cautiously entering the Delta Rana star system three days after receiving a distress call from the Federation colony on its fourth planet. The garbled transmission reported the colony under attack from an unidentified spacecraft. Our mission is one of rescue and, if necessary, confrontation with a hostile force."
                        ]
                }
                ...
}

_class что _class свойства _class установлено полное имя класса Log .

Следующим шагом является настройка MongoTemplate для выполнения теста.

LocalhostMongoAppConfig

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@Configuration
@Profile("test")
public class LocalhostMongoAppConfig {
 
        private static final String DATABASE_NAME = "logs";
 
        public @Bean Mongo mongo() throws UnknownHostException, MongoException {
                Mongo mongo = new Mongo("localhost");
                return mongo;
        }
 
        public @Bean MongoTemplate mongoTemplate() throws UnknownHostException, MongoException {
                MongoTemplate mongoTemplate = new MongoTemplate(mongo(), DATABASE_NAME);
                return mongoTemplate;
        }
 
}

Обратите внимание, что этот объект MongoTemplate будет создаваться только тогда, когда активен тестовый профиль.

И теперь мы можем написать тестовый пример JUnit :

WhenAlmiralWantsToReadLogs

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:com/lordofthejars/nosqlunit/springdata/mongodb/log/application-context-test.xml")
@ActiveProfiles("test")
@UsingDataSet(locations = "all-logs.json", loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public class WhenAlmiralWantsToReadLogs {
 
        @ClassRule
        public static ManagedMongoDb managedMongoDb = newManagedMongoDbRule()
                        .mongodPath(
                                        "/Users/alexsotobueno/Applications/mongodb-osx-x86_64-2.0.5")
                        .build();
 
        @Rule
        public MongoDbRule mongoDbRule = newMongoDbRule().defaultManagedMongoDb("logs");
 
        @Autowired
        private LogManager logManager;
 
        @Test
        public void all_entries_should_be_loaded() {
 
                List<Log> allLogs = logManager.findAll();
                assertThat(allLogs, hasSize(3));
 
        }
 
}

В предыдущем классе есть несколько важных моментов, на которые стоит обратить внимание:

  1. Поскольку NoSQLUnit использует правила JUnit, вы можете свободно использовать @RunWith(SpringJUnit4ClassRunner) .
  2. Используя @ActiveProfiles мы загружаем тестовую конфигурацию вместо производственных.
  3. Вы можете без проблем использовать Spring аннотации типа @Autowired .

Выводы

Не существует большой разницы между написанием тестов ни для одного Spring Data MongoDB и для приложений, которые его используют. Только помните, чтобы правильно _class свойство _class .

Ссылка: тестирование Spring-приложений MongoDB с NoSQLUnit от нашего партнера по JCG Алекса Сото в блоге One Jar To Rule All .