File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
package kr.itn.itnhub.mattermost;
import com.github.tomakehurst.wiremock.WireMockServer;
import kr.itn.itnhub.config.MattermostProperties;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.web.client.RestClient;
import java.net.http.HttpClient;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
class MattermostRestClientTest {
private WireMockServer server;
private MattermostRestClient client;
@BeforeEach
void setUp() {
server = new WireMockServer(options().dynamicPort());
server.start();
MattermostProperties props = new MattermostProperties(
"http://localhost:" + server.port(),
"test-token",
"team123",
"문정원",
"법률검토");
// 이 HTTP/1.1 고정은 테스트 하네스(WireMock/Jetty)만의 제약이다: JDK 21 HttpClient의
// 기본 h2c 업그레이드 협상이 WireMock 상대로 POST 요청에서 간헐적으로 RST_STREAM을
// 유발하기 때문에 여기서만 고정한다. 운영 환경은 HTTPS/ALPN으로 협상하므로 해당되지 않는다.
HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.build();
RestClient.Builder builder = RestClient.builder()
.requestFactory(new JdkClientHttpRequestFactory(httpClient));
client = new MattermostRestClient(props, builder);
}
@AfterEach
void tearDown() {
server.stop();
}
@Test
void 내부명으로_채널을_찾으면_id를_돌려준다() {
server.stubFor(get(urlEqualTo("/api/v4/teams/team123/channels/name/org-001-mj"))
.willReturn(okJson("{\"id\":\"chan001mj\",\"name\":\"org-001-mj\"}")));
assertThat(client.findChannelIdByInternalName("org-001-mj"))
.contains("chan001mj");
}
@Test
void 내부명으로_채널이_없으면_빈값이다() {
server.stubFor(get(urlEqualTo("/api/v4/teams/team123/channels/name/org-999-mj"))
.willReturn(aResponse().withStatus(404)));
assertThat(client.findChannelIdByInternalName("org-999-mj")).isEmpty();
}
@Test
void 토큰을_Authorization_헤더로_보낸다() {
server.stubFor(get(urlEqualTo("/api/v4/teams/team123/channels/name/org-001-mj"))
.willReturn(okJson("{\"id\":\"chan001mj\"}")));
client.findChannelIdByInternalName("org-001-mj");
server.verify(getRequestedFor(urlEqualTo("/api/v4/teams/team123/channels/name/org-001-mj"))
.withHeader("Authorization", equalTo("Bearer test-token")));
}
@Test
void 표시명으로_내_채널목록에서_id를_찾는다() {
server.stubFor(get(urlPathEqualTo("/api/v4/users/me/teams/team123/channels"))
.willReturn(okJson("""
[
{"id":"aaa","display_name":"001_국제방송교류재단 (문정원)"},
{"id":"bbb","display_name":"001_국제방송교류재단 (법률검토)"}
]
""")));
assertThat(client.findChannelIdByDisplayName("001_국제방송교류재단 (법률검토)"))
.contains("bbb");
assertThat(client.findChannelIdByDisplayName("002_없는기관 (문정원)"))
.isEmpty();
}
@Test
void 비공개_채널을_생성하고_id를_돌려준다() {
server.stubFor(post(urlEqualTo("/api/v4/channels"))
.willReturn(okJson("{\"id\":\"newchan\"}")));
String id = client.createPrivateChannel("org-002-mj", "002_세종학당재단 (문정원)");
assertThat(id).isEqualTo("newchan");
server.verify(postRequestedFor(urlEqualTo("/api/v4/channels"))
.withRequestBody(matchingJsonPath("$.team_id", equalTo("team123")))
.withRequestBody(matchingJsonPath("$.name", equalTo("org-002-mj")))
.withRequestBody(matchingJsonPath("$.display_name",
equalTo("002_세종학당재단 (문정원)")))
.withRequestBody(matchingJsonPath("$.type", equalTo("P"))));
}
@Test
void 서버가_오류를_주면_MattermostException을_던진다() {
server.stubFor(post(urlEqualTo("/api/v4/channels"))
.willReturn(aResponse().withStatus(500).withBody("boom")));
assertThatThrownBy(() -> client.createPrivateChannel("org-003-mj", "003_기관 (문정원)"))
.isInstanceOf(MattermostException.class);
}
}