Skip to content
Open
26 changes: 24 additions & 2 deletions spring-http-client-1/initial/src/main/java/cholog/Todo.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
package cholog;

//import lombok.AllArgsConstructor;
//import lombok.Data;

//@Data // getter, setter
//@NoArgsConstructor // 기본 생성자 생성
//@AllArgsConstructor // 모든 필드를 포함하는 생성자 생성
public class Todo {

// TODO: Todo 객체가 가지는 필드들을 정의
private Long userId;
private Long id;
private String title;
private boolean completed;

public Todo(Long userId, Long id, String title, boolean completed) { // -> AllArgsConstructor (Lombok)
this.userId = userId;
this.id = id;
this.title = title;
this.completed = completed;
}

public Long getUserId() { return userId; }

public Long getId() { return id; }

public String getTitle() {
return null;
return title;
}

public boolean getCompleted() { return completed; }
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package cholog;

import org.springframework.http.HttpStatus;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClient;

import java.util.Collections;
Expand All @@ -13,13 +15,48 @@ public TodoClientWithRestClient(RestClient restClient) {
}

public List<Todo> getTodos() {
// TODO: restClient의 get 메서드를 사용하여 요청을 보내고 결과를 Todo 리스트로 변환하여 반환
return Collections.emptyList();
//RestClient.builder().baseUrl("http://jsonplaceholder.typicode.com").build()
// String uri = "http://jsonplaceholder.typicode.com/todos";
List<Todo> todos = restClient.get()
.uri("/todos")
.retrieve()
.body(List.class);
return todos;
}

public Todo getTodoById(Long id) {
// TODO: restClient의 get 메서드를 사용하여 요청을 보내고 결과를 Todo로 변환하여 반환
// TODO: 존재하지 않는 id로 요청을 보낼 경우 TodoException.NotFound 예외를 던짐
return new Todo();
Todo todo = restClient.get()
.uri("/todos/{id}", id)
.retrieve()
.onStatus(status -> status.value() == 404, (req, res) -> {
throw new TodoException.NotFound(id);
})
.body(Todo.class);
return todo;
}

public Todo createTodo(Todo newTodo) {
Todo createdTodo = restClient.post()
.uri("/todos")
.body(newTodo)
.retrieve()
.body(Todo.class);
return createdTodo;
}

public Todo updateTodo(Long id, Todo updatedTodo) {
Todo updatedResult = restClient.put()
.uri("/todos/{id}", id)
.body(updatedTodo)
.retrieve()
.body(Todo.class);
return updatedResult;
}

public void deleteTodo(Long id) {
restClient.delete()
.uri("/todos/{id}", id)
.retrieve()
.toBodilessEntity(); // DELETE 요청에 대한 응답 본문이 필요 없으므로 toBodilessEntity 사용
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package cholog;

import org.springframework.http.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

public class TodoClientWithRestTemplate {
Expand All @@ -10,8 +12,58 @@ public TodoClientWithRestTemplate(RestTemplate restTemplate) {
}

public Todo getTodoById(Long id) {
// TODO: restTemplate을 사용하여 요청을 보내고 결과를 Todo로 변환하여 반환
// TODO: 존재하지 않는 id로 요청을 보낼 경우 TodoException.NotFound 예외를 던짐
return new Todo();
String resourceUrl = "http://jsonplaceholder.typicode.com/todos/{id}";
// String resourceUrl = "http://jsonplaceholder.typicode.com/todos/" + id;
try {
ResponseEntity<Todo> response = restTemplate.getForEntity(resourceUrl, Todo.class, id);
return response.getBody();
} catch (HttpClientErrorException e) {
if(e.getStatusCode() == HttpStatus.NOT_FOUND) {
throw new TodoException.NotFound(id);
} else {
throw new TodoException("다른 에러 : " + e.getMessage());
}
}
}

public Todo createTodo(Todo newTodo) {
String resourceUrl = "http://jsonplaceholder.typicode.com/todos";
try {
ResponseEntity<Todo> response = restTemplate.postForEntity(resourceUrl, newTodo, Todo.class);
return response.getBody();
} catch (HttpClientErrorException e) {
throw new TodoException("Todo 생성 중 에러 발생: " + e.getMessage());
}
}

public Todo updateTodo(Long id, Todo updatedTodo) {
String resourceUrl = "http://jsonplaceholder.typicode.com/todos/{id}";
try {
HttpEntity<Todo> requestUpdate = new HttpEntity<>(updatedTodo);
ResponseEntity<Todo> response = restTemplate.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Todo.class, id);
return response.getBody();
} catch (HttpClientErrorException e) {
if(e.getStatusCode() == HttpStatus.NOT_FOUND) {
throw new TodoException.NotFound(id);
} else {
throw new TodoException("Todo 업데이트 중 에러 발생: " + e.getMessage());
}
}
}

public HttpStatusCode deleteTodo(Long id) {
try {
String resourceUrl = "http://jsonplaceholder.typicode.com/todos/{id}";
restTemplate.delete(resourceUrl, id);
// ResponseEntity<Void> response = restTemplate.exchange(resourceUrl, HttpMethod.DELETE, null, Void.class, id);
// return response.getStatusCode();
return HttpStatus.OK;
} catch (HttpClientErrorException e) {
if(e.getStatusCode() == HttpStatus.NOT_FOUND) {
throw new TodoException.NotFound(id);
} else {
throw new TodoException("Todo 삭제 중 에러 발생: " + e.getMessage());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;

import java.util.List;

Expand Down Expand Up @@ -34,4 +36,34 @@ public void testGetTodoWithNonExistentId() {
assertThatThrownBy(() -> todoClient.getTodoById(nonExistentId))
.isInstanceOf(TodoException.NotFound.class);
}

@Test
public void testCreateTodo() {
Todo newTodo = new Todo(2L, 2L, "New Todo", false);
Todo createdTodo = todoClient.createTodo(newTodo);

assertThat(createdTodo).isNotNull();
assertThat(createdTodo.getTitle()).isEqualTo(newTodo.getTitle());
}

@Test
public void testUpdateTodo() {
testCreateTodo();

Todo updatedTodo = new Todo(2L, 2L, "Updated Todo", true);
Todo resultTodo = todoClient.updateTodo(2L, updatedTodo);

assertThat(resultTodo).isNotNull();
assertThat(resultTodo.getTitle()).isEqualTo("Updated Todo");
}

@Test
public void testDeleteTodo() {
todoClient.deleteTodo(2L);

//삭제된 후, 해당 id로 getTodoById를 호출하면 TodoException.NotFound 예외가 발생하는지를 검증
// 예외를 발생하는지 -> NotFound class 인지
// assertThatThrownBy(() -> todoClient.getTodoById(2L)).isInstanceOf(TodoException.NotFound.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
Expand All @@ -26,4 +30,31 @@ public void testGetTodoWithNonExistentId() {
assertThatThrownBy(() -> todoClient.getTodoById(nonExistentId))
.isInstanceOf(TodoException.NotFound.class);
}

@Test
public void testCreateTodo() {
Todo newTodo = new Todo(2L, 2L, "New Todo", false);
Todo createdTodo = todoClient.createTodo(newTodo);

assertThat(createdTodo).isNotNull();
assertThat(createdTodo.getTitle()).isEqualTo(newTodo.getTitle());
}

@Test
public void testUpdateTodo() {
testCreateTodo();

Todo updatedTodo = new Todo(2L, 2L, "Updated Todo", true);
Todo resultTodo = todoClient.updateTodo(2L, updatedTodo);

assertThat(resultTodo).isNotNull();
assertThat(resultTodo.getTitle()).isEqualTo("Updated Todo");
}

@Test
public void testDeleteTodo() {
// DELETE 요청을 보내고 상태 코드 확인
HttpStatusCode deleteStatus = todoClient.deleteTodo(3L);
assertThat(deleteStatus).isEqualTo(HttpStatus.OK); // 204 No Content 확인
}
}