Skip to content
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>This test verifies that GreetingService correctly interacts with {@link TodoService} and
* reflects the number of open (not completed) todos in the message.
*
* <p>Initially marked {@link Disabled} to be enabled by the developer after implementation.
* <p>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;
Expand Down Expand Up @@ -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
Expand All @@ -94,5 +96,4 @@ void should_ignore_null_todos_or_null_completed_flags() {
// then
assertThat(message).contains("1 open task");
}
*/
}
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -48,12 +39,12 @@ void shouldCreateAndRetrieveTodo() {
String createdBy = "test-user";

// when
Todo created = todoService.createTodo(title, description, completed, createdBy);
List<Todo> allTodos = todoService.getAllTodos();
todoService.createTodo(title, description, completed, createdBy);
List<Todo> 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);
Expand Down Expand Up @@ -110,6 +101,6 @@ void shouldSearchByTitle() {

// then
assertThat(result).hasSize(1);
assertThat(result.get(0).title()).containsIgnoringCase("milk");
assertThat(result.getFirst().title()).containsIgnoringCase("milk");
}
}
Loading