Commit 88a9d76f authored by Alexander's avatar Alexander
Browse files

Upd 17 FINAL. issue https://resprojects.ru/issues/160

Final changes for this branch

1) In pom.xml changed program version
2) Some changes in README file
3) In GraphDTO.EdgeGraph class some changes. For validator annotation @NotBlank was added text message
4) In GraphEdgeServiceImpl class some changes. For get method was added data checking and thows exception if data incorrect
5) In enum type ErrorType was deleted unused error type
6) In ValidationUtil class some changes for validation messages
7) Was deleted unused tests
8) Some changes in GraphEdgeServiceH2DBTests. Was added new unit tests and renamed exists tests.
9) Some changes in GraphEdgeServiceMockTests
10) In TestUtils was removed unused method
11) Was added unit tests for GraphEdgeRestController
parent 606063bd
Pipeline #83 passed with stages
in 1 minute and 21 seconds
......@@ -43,7 +43,7 @@ package:
script:
- echo "Packing into an executable jar file using maven"
- mvn package
- "cp target/linkchecker-0.0.1-SNAPSHOT.jar linkchecker.jar"
- "cp target/linkchecker-0.1.0.jar linkchecker.jar"
- "ls -l"
artifacts:
......
......@@ -7,30 +7,56 @@
Сервис должен реализовывать два POST-метода:
1. setNodes устанавливает граф из узлов, описанных выше. Формат входных данных - JSON. Программа должна исключать циклические связи узлов.
2. checkRoute принимает набор вершин (или их идентификаторов) в формате JSON и проходит по этим вершинам, проверяя на каждом пройденном узле, не отказал ли он. Если путь существует в графе и ни один из узлов пути не отказал, следует увеличить счетчик в каждом из узлов пути. В противном случае отображать ошибку в ответе POST-метода (произвольный формат).
1. setNodes устанавливает граф из узлов, описанных выше. Формат входных данных - JSON.
Программа должна исключать циклические связи узлов.
2. checkRoute принимает набор вершин (или их идентификаторов) в формате JSON
и проходит по этим вершинам, проверяя на каждом пройденном узле, не отказал ли он.
Если путь существует в графе и ни один из узлов пути не отказал, следует увеличить счетчик
в каждом из узлов пути. В противном случае отображать ошибку в ответе POST-метода (произвольный формат).
3. Узлы и связи должны храниться в базе данных.
## Личная инициатива
## Изменённый вариант задания
После введённых корректировок, итоговый вид тестового задания выглядит следующим образом:
Разработать REST-сервис, проверяющий работоспособность любой последовательности узлов.
1. Каждый узел имеет уникальное имя и счетчик успешно выполненных запросов, так же для хранения в базе данных есть уникальный идентификатор, который присваивается автоматически при записи в БД. Был исключен элемент вероятность отказа узла. Этот параметр перестал быть нужным, так как вероятность отказа узла стала случайным фактором, возникающая автоматически, во время проверки последовательности узлов.
1. Граф в программе неориентированный, т.е. вершины графа связаны друг с другом рёбрами, не имеющими направления. В базе данных, хранение графа осуществляется в двух таблицах. В одной таблице осуществляется хранение набора узлов графа, в другой набор рёбер графа. Более подробно смотрите запись в wiki [Описание данных](https://gitlab.resprojects.ru/mrresident/linkchecker/wikis/%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85)
1. Каждый узел имеет уникальное имя и счетчик успешно выполненных запросов,
так же для хранения в базе данных есть уникальный идентификатор, который
присваивается автоматически при записи в БД. Был исключен элемент вероятность отказа узла.
Этот параметр перестал быть нужным, так как вероятность отказа узла стала случайным фактором,
возникающая автоматически, во время проверки последовательности узлов.
1. Граф в программе неориентированный, т.е. вершины графа связаны друг с другом рёбрами,
не имеющими направления. В базе данных, хранение графа осуществляется в двух таблицах.
В одной таблице осуществляется хранение набора узлов графа, в другой набор рёбер графа.
Более подробно смотрите запись в wiki [Описание данных](https://gitlab.resprojects.ru/mrresident/linkchecker/wikis/%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85)
1. Программа позволяет делать следующее:
1. Работать с графом обобщённо:
1. Создавать новый граф (при этом информация о прежнем графе будет удалена с БД)
1. Извлекать информацию о графе в заданном формате
1. Удалять целиком весь граф
1. Проверять работоспособность заданной последовательности узлов (по условию задачи) выполнив соответствующий запрос.
1. Работать с узлами и ребрами по отдельности, т.е. добавлять, удалять, искать информацию по заданным параметрам. Ручное изменение какой-либо информации о узле и ребре не предусмотрена, т.е. возможно либо добавления узла или ребра в БД или удаление из БД)
Так как по условию задания, граф должен исключить все виды циклов (т.е. граф должен быть ациклическим), то при любом запросе информации о графе целиком или же при проверки набора заданных узлов будет происходить автоматический поиск и удаление циклов из графа. Удаление циклов происходит при помощи удаления набора рёбер, создающие циклы. Поэтому в случае обнаружения циклов в графе, исходный набор рёбер будет отличаться от набора рёбер хранящихся в БД.
Автоматический поиск и удаление циклов не срабатывает, если происходит работа только с набором данных рёбер графа в отдельности, т.е. можно добавлять в базу рёбра, образующие циклы.
**Используемый стек** : Spring Boot, Spring Data, ORM (Hibernate), [JGraphT](https://jgrapht.org/) (для работы с графом), GSON (используется вместо используемого по умолчанию Jackson для работы с json), Thymeleaf и Bootstrap (используется для формирования стартовой информационной страницы), Mockito (идёт вместе с Spring Boot), Powermock (подключается отдельной библиотекой, используется в дополнении к mockito для тестов)
1. Проверять работоспособность заданной последовательности узлов
(по условию задачи) выполнив соответствующий запрос.
1. Работать с узлами и ребрами по отдельности, т.е. добавлять, удалять,
искать информацию по заданным параметрам. Ручное изменение какой-либо информации о узле и ребре не предусмотрена,
т.е. возможно либо добавления узла или ребра в БД или удаление из БД)
Так как по условию задания, граф должен исключить все виды циклов
(т.е. граф должен быть ациклическим), то при любом запросе информации о графе целиком
или же при проверки набора заданных узлов будет происходить автоматический поиск
и удаление циклов из графа. Удаление циклов происходит при помощи удаления набора рёбер,
создающие циклы. Поэтому в случае обнаружения циклов в графе, исходный набор рёбер будет
отличаться от набора рёбер хранящихся в БД.
Автоматический поиск и удаление циклов не срабатывает, если происходит работа только
с набором данных рёбер графа в отдельности, т.е. можно добавлять в базу рёбра,
образующие циклы.
**Используемый стек** : **Spring Boot**, **Spring Data**, **ORM (Hibernate)**,
[**JGraphT**](https://jgrapht.org/) (для работы с графом),
**GSON** (используется вместо используемого по умолчанию Jackson для работы с json),
**Thymeleaf** и **Bootstrap** (используется для формирования стартовой информационной страницы),
**Mockito** (идёт вместе с Spring Boot),
**Powermock** (подключается отдельной библиотекой, используется в дополнении к mockito для тестов)
**Хранилище данных** : PostgeSQL (для production), H2 (для тестов)
\ No newline at end of file
......@@ -10,7 +10,7 @@
</parent>
<groupId>ru.resprojects</groupId>
<artifactId>linkchecker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.1.0</version>
<name>linkchecker</name>
<description>Linkchecker (test project)</description>
......
......@@ -111,14 +111,14 @@ public class GraphDto {
/**
* Unique name of first graph node.
*/
@NotBlank
@NotBlank(message = "nodeOne: " + VALIDATOR_NODE_NOT_BLANK_NAME_MESSAGE)
@Size(min = MIN_NAME_SIZE, max = MAX_NAME_SIZE)
private String nodeOne;
/**
* Unique name of second graph node.
*/
@NotBlank
@NotBlank(message = "nodeTwo: " + VALIDATOR_NODE_NOT_BLANK_NAME_MESSAGE)
@Size(min = MIN_NAME_SIZE, max = MAX_NAME_SIZE)
private String nodeTwo;
......
......@@ -204,7 +204,12 @@ public class GraphEdgeServiceImpl implements GraphEdgeService {
@Override
public Set<EdgeGraph> get(final String nodeName) {
return GraphUtil.edgesToEdgeGraphs(getEdges(nodeName));
List<Edge> result = getEdges(nodeName);
if (result.isEmpty()) {
throw new NotFoundException(String.format(properties.getEdgeMsg()
.get("EDGE_MSG_GET_BY_NAME_ERROR"), nodeName), ErrorPlaceType.EDGE);
}
return GraphUtil.edgesToEdgeGraphs(result);
}
private List<Edge> getEdges(final String nodeName) {
......@@ -216,8 +221,8 @@ public class GraphEdgeServiceImpl implements GraphEdgeService {
public EdgeGraph getById(final Integer id) throws NotFoundException {
EdgeGraph edgeGraph = GraphUtil.edgeToEdgeGraph(edgeRepository.findById(id)
.orElse(null));
return checkNotFound(edgeGraph, String.format(properties.getAppMsg().get("MSG_BY_ID_ERROR"), ErrorPlaceType.EDGE, id),
ErrorPlaceType.EDGE);
return checkNotFound(edgeGraph, String.format(properties.getAppMsg().get("MSG_BY_ID_ERROR"),
ErrorPlaceType.EDGE, id), ErrorPlaceType.EDGE);
}
@Override
......
......@@ -16,8 +16,8 @@ public final class ValidationUtil {
public static final int MIN_NAME_SIZE = 1;
public static final int MAX_NAME_SIZE = 20;
public static final String VALIDATOR_NOT_NULL_MESSAGE = "Object must not be null";
public static final String VALIDATOR_NODE_NOT_BLANK_NAME_MESSAGE = "Value must not be empty";
public static final String VALIDATOR_NODE_NAME_RANGE_MESSAGE = "Value must be at range from "
public static final String VALIDATOR_NODE_NOT_BLANK_NAME_MESSAGE = "Node name must not be empty";
public static final String VALIDATOR_NODE_NAME_RANGE_MESSAGE = "Node name must be at range from "
+ MIN_NAME_SIZE + " to " + MAX_NAME_SIZE;
private ValidationUtil() {
......
......@@ -8,5 +8,4 @@ public enum ErrorType {
DATA_NOT_FOUND, //Types of errors that are associated with search and extract data
DATA_ERROR, //Types of errors that are associated with data handling
VALIDATION_ERROR, //Types of errors are associated with validating data in REST-controllers
WRONG_REQUEST
}
package ru.resprojects.linkchecker;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LinkcheckerApplication.class)
public class LinkcheckerApplicationTests {
private static final Logger LOG = LoggerFactory.getLogger(LinkcheckerApplicationTests.class);
@Autowired
private AppProperties prop;
@Test
public void contextLoads() {
}
@Test
public void stub() {
LOG.debug("NOTHING");
Set<String> stringSet = Stream.of("v1", "v2").collect(Collectors.toSet());
Set<Integer> intSet = Stream.of(1, 2).collect(Collectors.toSet());
Set<Double> doubleSet = Stream.of(1.0, 2.0).collect(Collectors.toSet());
genericCollection(stringSet);
genericCollection(intSet);
genericCollection(doubleSet);
LOG.debug(prop.getAppMsg().toString());
LOG.debug(prop.getNodeMsg().toString());
LOG.debug(prop.getEdgeMsg().toString());
}
private <T> void genericCollection(final Set<T> coll) {
if (Objects.nonNull(coll) && !coll.isEmpty()) {
T col = coll.iterator().next();
if (col instanceof String || col instanceof Integer) {
LOG.debug("The collection has a valid type = " + col.getClass().getName());
} else {
LOG.debug("The collection do not have a valid type");
}
}
}
}
......@@ -30,10 +30,6 @@ public class TestUtils {
private TestUtils() {
}
public static String mapToJson(Object obj, Type type) {
return new Gson().toJson(obj, type);
}
public static String mapToJson(Object obj) {
return new Gson().toJson(obj);
}
......
......@@ -15,6 +15,7 @@ import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.context.junit4.SpringRunner;
import ru.resprojects.linkchecker.AppProperties;
import ru.resprojects.linkchecker.LinkcheckerApplication;
import ru.resprojects.linkchecker.TestUtils;
import ru.resprojects.linkchecker.util.exeptions.ApplicationException;
import ru.resprojects.linkchecker.util.exeptions.NotFoundException;
......@@ -57,14 +58,14 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionOneWhileCreateEdge() {
public void createEdgeNullArgumentException() {
thrown.expect(ApplicationException.class);
thrown.expectMessage(properties.getAppMsg().get("MSG_ARGUMENT_NULL"));
edgeService.create((EdgeGraph) null);
}
@Test
public void exceptionTwoWhileCreateEdge() {
public void createEdgeNodeNotFoundException() {
EdgeGraph edgeGraph = new EdgeGraph("v10", "v4");
thrown.expect(NotFoundException.class);
thrown.expectMessage( String.format(properties.getNodeMsg().get("NODE_MSG_BY_NAME_ERROR"), "v10"));
......@@ -72,7 +73,7 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionThreeWhileCreateEdge() {
public void createEdgeAlreadyPresentException() {
EdgeGraph edgeGraph = new EdgeGraph("v1", "v2");
thrown.expect(ApplicationException.class);
thrown.expectMessage(String.format(properties.getEdgeMsg().get("EDGE_MSG_ALREADY_PRESENT_ERROR"), "v1", "v2", "v2", "v1"));
......@@ -80,7 +81,7 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionFourWhileCreateEdge() {
public void createEdgeAlreadyPresentVariantTwoException() {
EdgeGraph edgeGraph = new EdgeGraph("v2", "v1");
thrown.expect(ApplicationException.class);
thrown.expectMessage(String.format(properties.getEdgeMsg().get("EDGE_MSG_ALREADY_PRESENT_ERROR"), "v2", "v1", "v1", "v2"));
......@@ -104,14 +105,14 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionOneWhileCreateEdges() {
public void createEdgesEmptyCollectionException() {
thrown.expect(ApplicationException.class);
thrown.expectMessage(properties.getAppMsg().get("MSG_COLLECTION_EMPTY"));
edgeService.create(new HashSet<>());
}
@Test
public void exceptionTwoWhileCreateEdges() {
public void createEdgesNodeNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getNodeMsg().get("NODE_MSG_BY_NAME_ERROR"), "v21"));
Set<EdgeGraph> edgeGraphs = Stream.of(
......@@ -123,7 +124,7 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionThreeWhileCreateEdges() {
public void createEdgesCollectionContainNullException() {
thrown.expect(ApplicationException.class);
thrown.expectMessage(properties.getAppMsg().get("MSG_COLLECTION_CONTAIN_NULL"));
Set<EdgeGraph> edgeGraphs = Stream.of(
......@@ -135,7 +136,7 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionFourWhileCreateEdges() {
public void createEdgesEdgeAlreadyPresentException() {
thrown.expect(ApplicationException.class);
thrown.expectMessage(String.format(properties.getEdgeMsg().get("EDGE_MSG_ALREADY_PRESENT_ERROR"), "v1", "v2", "v2", "v1"));
Set<EdgeGraph> edgeGraphs = Stream.of(
......@@ -154,7 +155,7 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionWhileDeleteEdgeById() {
public void deleteEdgeByIdNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getAppMsg().get("MSG_BY_ID_ERROR"), "EDGE", 5022));
edgeService.delete(5022);
......@@ -168,7 +169,7 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionWhileDeleteEdgeByNodeOneAndNodeTwoNames() {
public void deleteEdgeByNodeOneAndNodeTwoNamesNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getEdgeMsg().get("EDGE_MSG_GET_ERROR"), "v15", "v2"));
edgeService.delete("v15", "v2");
......@@ -182,7 +183,7 @@ public class GraphEdgeServiceH2DBTests {
}
@Test
public void exceptionWhileDeleteEdgeByNodeName() {
public void deleteEdgeByNodeNameNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getEdgeMsg().get("EDGE_MSG_GET_BY_NAME_ERROR"), "v15"));
edgeService.delete("v15");
......@@ -214,20 +215,41 @@ public class GraphEdgeServiceH2DBTests {
public void getEdgeById() {
EdgeGraph actual = edgeService.getById(5005);
Assert.assertNotNull(actual);
Assert.assertEquals(TestUtils.edgeGraph, actual);
LOG.debug(actual.toString());
}
@Test
public void getEdgeByIdNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getAppMsg().get("MSG_BY_ID_ERROR"), "EDGE", 7000));
edgeService.getById(7000);
}
@Test
public void getEdgesByNodeName() {
Set<EdgeGraph> actual = edgeService.get("v1");
Set<EdgeGraph> expected = TestUtils.edgesGraph.stream()
.filter(eg -> eg.getId() != 5008)
.collect(Collectors.toSet());
Assert.assertFalse(actual.isEmpty());
Assert.assertEquals(expected.size(), actual.size());
assertThat(actual).containsAnyOf(expected.iterator().next());
actual.forEach(eg -> LOG.debug("---- EDGE: " + eg));
}
@Test
public void getEdgesByNodeNameNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getEdgeMsg().get("EDGE_MSG_GET_BY_NAME_ERROR"), "v100"));
edgeService.get("v100");
}
@Test
public void getEdgeByNodeNameOneAndNodeNameTwo() {
EdgeGraph actual = edgeService.get("v1", "v2");
Assert.assertNotNull(actual);
Assert.assertEquals(TestUtils.edgeGraph, actual);
Integer actualId = actual.getId();
LOG.debug(actual.toString());
actual = edgeService.get("v2", "v1");
......
......@@ -84,7 +84,7 @@ public class GraphEdgeServiceMockTests {
}
@Test
public void exceptionOneWhileCreateEdge() {
public void createEdgeNodeNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getNodeMsg().get("NODE_MSG_BY_NAME_ERROR"), "v1"));
EdgeGraph edgeGraph = new EdgeGraph("v1", "v2");
......@@ -93,7 +93,7 @@ public class GraphEdgeServiceMockTests {
}
@Test
public void exceptionTwoWhileCreateEdge() {
public void createEdgeNullArgumentException() {
thrown.expect(ApplicationException.class);
thrown.expectMessage(properties.getAppMsg().get("MSG_ARGUMENT_NULL"));
edgeService.create((EdgeGraph) null);
......@@ -121,7 +121,7 @@ public class GraphEdgeServiceMockTests {
}
@Test
public void exceptionOneWhileCreateEdges() {
public void createEdgesNodeNotFoundException() {
List<Edge> edges = Stream.of(
new Edge(5005,nodes.get(0), nodes.get(1)),
new Edge(5006,nodes.get(0), nodes.get(2)),
......@@ -138,21 +138,21 @@ public class GraphEdgeServiceMockTests {
}
@Test
public void exceptionTwoWhileCreateEdges() {
public void createEdgesNullArgumentException() {
thrown.expect(ApplicationException.class);
thrown.expectMessage(properties.getAppMsg().get("MSG_ARGUMENT_NULL"));
edgeService.create((Set<EdgeGraph>) null);
}
@Test
public void exceptionThreeWhileCreateEdges() {
public void createEdgesEmptyCollectionException() {
thrown.expect(ApplicationException.class);
thrown.expectMessage(properties.getAppMsg().get("MSG_COLLECTION_EMPTY"));
edgeService.create(new HashSet<>());
}
@Test
public void exceptionFourWhileCreateEdges() {
public void createEdgesCollectionContainNullException() {
thrown.expect(ApplicationException.class);
thrown.expectMessage(properties.getAppMsg().get("MSG_COLLECTION_CONTAIN_NULL"));
Set<EdgeGraph> edgeGraphs = new HashSet<>();
......@@ -174,7 +174,7 @@ public class GraphEdgeServiceMockTests {
}
@Test
public void exceptionWhileDeleteEdgeById() {
public void deleteEdgeByIdNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getAppMsg().get("MSG_BY_ID_ERROR"), "EDGE", 5050));
when(edgeRepository.existsById(5050)).thenReturn(false);
......@@ -200,7 +200,7 @@ public class GraphEdgeServiceMockTests {
}
@Test
public void exceptionWhileDeleteEdgesByNodeName() {
public void deleteEdgesByNodeNameNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getEdgeMsg().get("EDGE_MSG_GET_BY_NAME_ERROR"), "v1"));
List<Edge> emptyList = new ArrayList<>();
......@@ -220,7 +220,7 @@ public class GraphEdgeServiceMockTests {
}
@Test
public void exceptionWhileDeleteEdgeByNodeNameOneAndNodeNameTwo() {
public void deleteEdgeByNodeNameOneAndNodeNameTwoNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getEdgeMsg().get("EDGE_MSG_GET_ERROR"), "v1", "v2"));
edgeService.delete("v1", "v2");
......@@ -261,7 +261,7 @@ public class GraphEdgeServiceMockTests {
}
@Test
public void exceptionWhileGetEdgeById() {
public void getEdgeByIdNotFoundException() {
thrown.expect(NotFoundException.class);
thrown.expectMessage(String.format(properties.getAppMsg().get("MSG_BY_ID_ERROR"), "EDGE", 7000));
edgeService.getById(7000);
......
package ru.resprojects.linkchecker.web.rest;
import com.google.gson.reflect.TypeToken;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import ru.resprojects.linkchecker.AppProperties;
import ru.resprojects.linkchecker.LinkcheckerApplication;
import ru.resprojects.linkchecker.TestUtils;
import ru.resprojects.linkchecker.util.exeptions.ErrorInfo;
import ru.resprojects.linkchecker.util.exeptions.ErrorPlaceType;
import ru.resprojects.linkchecker.util.exeptions.ErrorType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static ru.resprojects.linkchecker.dto.GraphDto.EdgeGraph;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LinkcheckerApplication.class)
@ActiveProfiles(profiles = "test")
@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD,
scripts = {"classpath:schema-h2.sql", "classpath:data-h2.sql"},
config = @SqlConfig(encoding = "UTF-8"))
@WebAppConfiguration
public class GraphEdgeRestControllerTests {
private static final Logger LOG = LoggerFactory.getLogger(GraphRestControllerTests.class);
private MockMvc mvc;
@Autowired
WebApplicationContext webContext;
@Autowired
private AppProperties properties;
@Before
public void init() {
mvc = MockMvcBuilders.webAppContextSetup(webContext).build();
}
@Test
public void addNewEdge() throws Exception {
EdgeGraph newEdge = new EdgeGraph("v1", "v4");
MvcResult result = this.mvc.perform(post(GraphEdgeRestController.EDGE_REST_URL)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(TestUtils.mapToJson(newEdge))).andReturn();
Assert.assertEquals(HttpStatus.CREATED.value(), result.getResponse().getStatus());
EdgeGraph returnedEdge = TestUtils.mapFromJson(result.getResponse().getContentAsString(), EdgeGraph.class);
Assert.assertNotNull(returnedEdge);
Assert.assertEquals(newEdge.getNodeOne(), returnedEdge.getNodeOne());
Assert.assertEquals(newEdge.getNodeTwo(), returnedEdge.getNodeTwo());
Assert.assertNotNull(returnedEdge.getId());
}
@Test
public void addNewEdgeValidationException() throws Exception {
MvcResult result = this.mvc.perform(post(GraphEdgeRestController.EDGE_REST_URL)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(TestUtils.mapToJson(new EdgeGraph()))).andReturn();
Assert.assertEquals(HttpStatus.UNPROCESSABLE_ENTITY.value(), result.getResponse().getStatus());
ErrorInfo error = TestUtils.mapFromJson(result.getResponse().getContentAsString(), ErrorInfo.class);
Assert.assertEquals(ErrorType.VALIDATION_ERROR, error.getType());
Assert.assertEquals(ErrorPlaceType.APP, error.getPlace());
LOG.debug(Arrays.asList(error.getMessages()).toString());
}
@Test
public void addNewEdgeAlreadyPresentException() throws Exception {
EdgeGraph newEdge = new EdgeGraph("v1", "v2");
MvcResult result = this.mvc.perform(post(GraphEdgeRestController.EDGE_REST_URL)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(TestUtils.mapToJson(newEdge))).andReturn();
Assert.assertEquals(HttpStatus.UNPROCESSABLE_ENTITY.value(), result.getResponse().getStatus());
ErrorInfo error = TestUtils.mapFromJson(result.getResponse().getContentAsString(), ErrorInfo.class);
Assert.assertEquals(ErrorType.DATA_ERROR, error.getType());
Assert.assertEquals(ErrorPlaceType.EDGE, error.getPlace());
List<String> errMsgs = Arrays.asList(error.getMessages());
Assert.assertTrue(errMsgs.contains(String.format(properties.getEdgeMsg().get("EDGE_MSG_ALREADY_PRESENT_ERROR"),
newEdge.getNodeOne(), newEdge.getNodeTwo(),
newEdge.getNodeTwo(), newEdge.getNodeOne())));
LOG.debug(errMsgs.toString());
}
@Test
public void addNewEdges() throws Exception {