diff --git a/src/main/java/lv/ctco/springboottemplate/features/greeting/GreetingController.java b/src/main/java/lv/ctco/springboottemplate/features/greeting/GreetingController.java new file mode 100644 index 0000000..ed6b5b5 --- /dev/null +++ b/src/main/java/lv/ctco/springboottemplate/features/greeting/GreetingController.java @@ -0,0 +1,24 @@ +package lv.ctco.springboottemplate.features.greeting; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/greeting") +@Tag(name = "Greeting Controller", description = "Greeting related endpoints") +public class GreetingController { + private final GreetingService greetingService; + + public GreetingController(GreetingService greetingService) { + this.greetingService = greetingService; + } + + @GetMapping + @Operation(summary = "Get greeting message") + public String getGreeting() { + return greetingService.greet(); + } +} diff --git a/src/main/java/lv/ctco/springboottemplate/features/greeting/GreetingService.java b/src/main/java/lv/ctco/springboottemplate/features/greeting/GreetingService.java new file mode 100644 index 0000000..2d5770a --- /dev/null +++ b/src/main/java/lv/ctco/springboottemplate/features/greeting/GreetingService.java @@ -0,0 +1,20 @@ +package lv.ctco.springboottemplate.features.greeting; + +import lv.ctco.springboottemplate.features.todo.TodoService; +import org.springframework.stereotype.Service; + +@Service +public class GreetingService { + private final TodoService todoService; + + public GreetingService(TodoService todoService) { + this.todoService = todoService; + } + + public String greet() { + long activeTodosCount = + todoService.getAllTodos().stream().filter(todo -> !todo.completed()).count(); + + return String.format("Hello from Spring! You have %d open tasks.", activeTodosCount); + } +} diff --git a/src/test/java/lv/ctco/springboottemplate/features/greeting/GreetingServiceIntegrationTest.java b/src/test/java/lv/ctco/springboottemplate/features/greeting/GreetingServiceIntegrationTest.java index eda5f13..ddcc817 100644 --- a/src/test/java/lv/ctco/springboottemplate/features/greeting/GreetingServiceIntegrationTest.java +++ b/src/test/java/lv/ctco/springboottemplate/features/greeting/GreetingServiceIntegrationTest.java @@ -1,32 +1,34 @@ package lv.ctco.springboottemplate.features.greeting; +import lv.ctco.springboottemplate.features.todo.Todo; +import lv.ctco.springboottemplate.features.todo.TodoRepository; import lv.ctco.springboottemplate.features.todo.TodoService; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestConstructor; -import org.testcontainers.junit.jupiter.Testcontainers; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; /** - * Integration test for {@link GreetingService}. + * Integration test for {@link GreetingService} without Testcontainers. * - *

This test verifies that GreetingService correctly interacts with {@link TodoService} and - * reflects the number of open (not completed) todos in the message. - * - *

Initially marked {@link Disabled} to be enabled by the developer after implementation. + *

This test uses a locally running MongoDB instance (expected at + * mongodb://localhost:27017/tododb). If you prefer an embedded/in-memory Mongo, add flapdoodle + * dependency and remove the dynamic property below. */ @SpringBootTest -@Disabled("Enable after implementing GreetingService using TodoService") -@Testcontainers @TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL) class GreetingServiceIntegrationTest { - /* - - @Container static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:6.0.8"); - + // Point Spring Data Mongo to a locally running MongoDB instead of using Testcontainers @DynamicPropertySource - static void setProperties(DynamicPropertyRegistry registry) { - registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl); + static void mongoProps(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.uri", () -> "mongodb://localhost:27017/tododb"); } private final TodoService todoService; @@ -74,10 +76,10 @@ void should_return_zero_open_tasks_message_if_none_exist() { @Test void should_work_with_no_todos_at_all() { // when - String message = greetingService.greet(); + String msg = greetingService.greet(); // then - assertThat(message).contains("Hello").contains("0 open tasks"); + assertThat(msg).contains("Hello").contains("0 open tasks"); } @Test @@ -94,5 +96,4 @@ void should_ignore_null_todos_or_null_completed_flags() { // then assertThat(message).contains("1 open task"); } - */ } diff --git a/src/test/java/lv/ctco/springboottemplate/features/todo/TodoServiceIntegrationTest.java b/src/test/java/lv/ctco/springboottemplate/features/todo/TodoServiceIntegrationTest.java index 7a98397..27436db 100644 --- a/src/test/java/lv/ctco/springboottemplate/features/todo/TodoServiceIntegrationTest.java +++ b/src/test/java/lv/ctco/springboottemplate/features/todo/TodoServiceIntegrationTest.java @@ -1,39 +1,30 @@ package lv.ctco.springboottemplate.features.todo; -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; -import org.springframework.test.context.TestConstructor; -import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest -@Testcontainers -@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL) class TodoServiceIntegrationTest { - @Container static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:6.0.8"); - @DynamicPropertySource static void setProperties(DynamicPropertyRegistry registry) { - registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl); + registry.add("spring.data.mongodb.uri", () -> "mongodb://localhost:27017/tododb"); } + @Autowired private TodoRepository todoRepository; + @Autowired private TodoService todoService; - public TodoServiceIntegrationTest(TodoRepository todoRepository, TodoService todoService) { - this.todoRepository = todoRepository; - this.todoService = todoService; - } - @BeforeEach void setup() { todoRepository.deleteAll(); @@ -48,12 +39,12 @@ void shouldCreateAndRetrieveTodo() { String createdBy = "test-user"; // when - Todo created = todoService.createTodo(title, description, completed, createdBy); - List allTodos = todoService.getAllTodos(); + todoService.createTodo(title, description, completed, createdBy); + List todos = todoService.getAllTodos(); // then - assertThat(allTodos).hasSize(1); - Todo todo = allTodos.get(0); + assertThat(todos).hasSize(1); + Todo todo = todos.getFirst(); assertThat(todo.id()).isNotNull(); assertThat(todo.title()).isEqualTo(title); @@ -110,6 +101,6 @@ void shouldSearchByTitle() { // then assertThat(result).hasSize(1); - assertThat(result.get(0).title()).containsIgnoringCase("milk"); + assertThat(result.getFirst().title()).containsIgnoringCase("milk"); } }