Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 32 additions & 25 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,38 @@
<java.version>11</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>


<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

</dependencies>

<build>
<plugins>
Expand All @@ -58,5 +66,4 @@
</plugins>
</build>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package com.example.postgresdemo.controller;

import com.example.postgresdemo.model.Question;
import com.example.postgresdemo.repository.QuestionRepository;

import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;


import java.nio.CharBuffer;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest

@AutoConfigureMockMvc
public class QuestionControllerTest {
@Autowired
private QuestionRepository questionRepository;

@Autowired
private MockMvc mockMvc;

@AfterEach
void deleteQuestions() {
questionRepository.deleteAll();
}

@Test
void testGetQuestionsWithAmountLessThanPageSize() throws Exception {
int assertionNumber = 10;
int pageSize = 20;

fillQuestions(assertionNumber);

mockMvc.perform(get("/questions")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(MockMvcResultMatchers.jsonPath("$.content.length()", Matchers.equalTo(assertionNumber)))
.andExpect(MockMvcResultMatchers.jsonPath("$.totalElements", Matchers.equalTo(assertionNumber)))
.andExpect(MockMvcResultMatchers.jsonPath("$.totalPages", Matchers.equalTo(1)));
}

@Test
void testGetQuestionsWithAmountMoreThanPageSize() throws Exception {
int assertionNumber = 30;
int pageSize = 20;
int totalPages = (int) Math.ceil(assertionNumber / (double) pageSize);

fillQuestions(assertionNumber);

mockMvc.perform(get("/questions")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(MockMvcResultMatchers.jsonPath("$.content.length()", Matchers.equalTo(pageSize)))
.andExpect(MockMvcResultMatchers.jsonPath("$.totalElements", Matchers.equalTo(assertionNumber)))
.andExpect(MockMvcResultMatchers.jsonPath("$.totalPages", Matchers.equalTo(totalPages)));
}

@Test
void testCreateCorrectQuestion() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/questions")
.contentType(MediaType.APPLICATION_JSON)
.content("{\n" +
" \"title\": \"Question 1\",\n" +
" \"description\": \"Description 1\"\n" +
"}"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(MockMvcResultMatchers.jsonPath("$.title", Matchers.equalTo("Question 1")))
.andExpect(MockMvcResultMatchers.jsonPath("$.description", Matchers.equalTo("Description 1")));
}

@Test
void testCreateQuestionWithoutTitle() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/questions")
.contentType(MediaType.APPLICATION_JSON)
.content("{\n" +
" \"description\": \"Description\"\n" +
"}"))
.andExpect(status().is4xxClientError());
}

@Test
void testCreateQuestionWithTitleLesThenThreeChars() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/questions")
.contentType(MediaType.APPLICATION_JSON)
.content("{\n" +
" \"title\": \"Te\",\n" +
" \"description\": \"Description\"\n" +
"}"))
.andExpect(status().is4xxClientError());
}

@Test
void testCreateQuestionWithTitleMoreThenHundredChars() throws Exception {
int numberOfChars = 101;
String title = CharBuffer.allocate(numberOfChars).toString().replace('\0', 'T');

mockMvc.perform(MockMvcRequestBuilders.post("/questions")
.contentType(MediaType.APPLICATION_JSON)
.content("{\n" +
" \"title\": \"" + title + "\",\n" +
" \"description\": \"Description\"\n" +
"}"))
.andExpect(status().is4xxClientError());
}

@Test
void testCreateQuestionWithoutDescription() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/questions")
.contentType(MediaType.APPLICATION_JSON)
.content("{\n" +
" \"title\": \"Question 1\"\n" +
"}"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(MockMvcResultMatchers.jsonPath("$.title", Matchers.equalTo("Question 1")))
.andExpect(MockMvcResultMatchers.jsonPath("$.description", Matchers.equalTo(null)));
}

@Test
void testUpdateQuestion() throws Exception {
fillQuestions(1);
long questionId = questionRepository.findAll().get(0).getId();

mockMvc.perform(MockMvcRequestBuilders.put("/questions/" + questionId)
.contentType(MediaType.APPLICATION_JSON)
.content("{\n" +
" \"title\": \"Edited Question 1\",\n" +
" \"description\": \"Edited Description 1\"\n" +
"}"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(MockMvcResultMatchers.jsonPath("$.title", Matchers.equalTo("Edited Question 1")))
.andExpect(MockMvcResultMatchers.jsonPath("$.description", Matchers.equalTo("Edited Description 1")));
}

@Test
void testUpdateQuestionWithNonExistingId() throws Exception {
fillQuestions(1);
long questionId = questionRepository.findAll().get(0).getId();

mockMvc.perform(MockMvcRequestBuilders.put("/questions/" + (questionId + 1))
.contentType(MediaType.APPLICATION_JSON)
.content("{\n" +
" \"title\": \"Edited Question 1\",\n" +
" \"description\": \"Edited Description 1\"\n" +
"}"))
.andExpect(status().is4xxClientError());
}

@Test
void testDeleteQuestion() throws Exception {
fillQuestions(1);
long questionId = questionRepository.findAll().get(0).getId();

mockMvc.perform(MockMvcRequestBuilders.delete("/questions/" + questionId)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}

private void fillQuestions(Integer number) {
for (int i = 0; i < number; i++) {
Question question = new Question();
question.setTitle("Question " + i);
question.setDescription("Description " + i);
questionRepository.save(question);
}
}
}
14 changes: 14 additions & 0 deletions src/test/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
spring.datasource.url=jdbc:h2:mem:test;MODE=PostgreSQL;
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}
# We add the MySQL Dialect so that it understands and generates the query based on MySQL
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
#spring.jpa.properties.hibernate.show_sql=true


spring.sql.init.mode=always