Skip to content

Commit a647030

Browse files
committed
feat: big refactor & WorkspaceControllerTest
1 parent d094fd3 commit a647030

4 files changed

Lines changed: 492 additions & 81 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.syncapi;
2+
3+
import org.springframework.http.MediaType;
4+
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
5+
import tools.jackson.core.JacksonException;
6+
import tools.jackson.databind.ObjectMapper;
7+
8+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
9+
10+
public class JsonTestUtil {
11+
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
12+
13+
private JsonTestUtil() {
14+
}
15+
16+
public static String toJson(Object object) {
17+
try {
18+
return OBJECT_MAPPER.writeValueAsString(object);
19+
} catch (JacksonException e) {
20+
throw new RuntimeException("Failed to serialize object to JSON", e);
21+
}
22+
}
23+
24+
public static MockHttpServletRequestBuilder postJson(String url, Object body) {
25+
return post(url)
26+
.contentType(MediaType.APPLICATION_JSON)
27+
.content(toJson(body));
28+
}
29+
30+
public static MockHttpServletRequestBuilder getJsonAuth(String url, String token) {
31+
return get(url)
32+
.header("Authorization", "Bearer " + token)
33+
.accept(MediaType.APPLICATION_JSON);
34+
}
35+
36+
public static MockHttpServletRequestBuilder postJsonAuth(String url, Object body, String token) {
37+
return post(url)
38+
.header("Authorization", "Bearer " + token)
39+
.contentType(MediaType.APPLICATION_JSON)
40+
.accept(MediaType.APPLICATION_JSON)
41+
.content(toJson(body));
42+
}
43+
44+
public static MockHttpServletRequestBuilder putJsonAuth(String url, Object body, String token) {
45+
return put(url)
46+
.header("Authorization", "Bearer " + token)
47+
.contentType(MediaType.APPLICATION_JSON)
48+
.accept(MediaType.APPLICATION_JSON)
49+
.content(toJson(body));
50+
}
51+
52+
public static MockHttpServletRequestBuilder deleteAuth(String url, String token) {
53+
return delete(url)
54+
.header("Authorization", "Bearer " + token)
55+
.accept(MediaType.APPLICATION_JSON);
56+
}
57+
}
Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,33 @@
11
package com.syncapi;
22

3-
import org.springframework.http.MediaType;
4-
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
5-
import tools.jackson.core.JacksonException;
6-
import tools.jackson.databind.ObjectMapper;
7-
83
import java.util.UUID;
94

10-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
11-
125
public class TestUtil {
136
public static String generateRandomEmail() {
14-
return "user-" + UUID.randomUUID() + "@example.com";
7+
return generateRandomValue("email") + "@example.com";
158
}
169

1710
public static String generateRandomName() {
18-
return "name-" + UUID.randomUUID();
11+
return generateRandomValue("name");
1912
}
2013

2114
public static String generateRandomPasswordHash() {
22-
return "hash-" + UUID.randomUUID();
15+
return generateRandomValue("hash");
2316
}
2417

2518
public static String generateRandomPassword() {
26-
return "pass-" + UUID.randomUUID();
19+
return generateRandomValue("password");
2720
}
2821

29-
public static String toJson(Object object) {
30-
try {
31-
return new ObjectMapper().writeValueAsString(object);
32-
} catch (JacksonException e) {
33-
throw new RuntimeException("Failed to serialize object to JSON", e);
34-
}
22+
public static String generateRandomValue(String prefix) {
23+
return prefix + "-" + UUID.randomUUID();
3524
}
3625

37-
public static <T> T fromJson(String json, Class<T> clazz) {
38-
try {
39-
return new ObjectMapper().readValue(json, clazz);
40-
} catch (JacksonException e) {
41-
throw new RuntimeException("Failed to deserialize JSON to object", e);
42-
}
26+
public static Long generateRandomId() {
27+
return Math.abs(UUID.randomUUID().getMostSignificantBits());
4328
}
4429

45-
public static MockHttpServletRequestBuilder postJson(String url, Object body) {
46-
return post(url)
47-
.characterEncoding("UTF-8")
48-
.content(toJson(body))
49-
.contentType(MediaType.APPLICATION_JSON);
30+
public static String generateRandomToken() {
31+
return generateRandomValue("token");
5032
}
5133
}
Lines changed: 87 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,167 @@
11
package com.syncapi.controller.auth;
22

3-
import com.syncapi.AbstractIntegrationTest;
3+
import com.syncapi.JsonTestUtil;
4+
import com.syncapi.TestUtil;
5+
import com.syncapi.dto.auth.AuthResponse;
46
import com.syncapi.dto.auth.LoginRequest;
57
import com.syncapi.dto.auth.RegisterRequest;
6-
import com.syncapi.entity.User;
78
import com.syncapi.repository.UserRepository;
8-
import org.junit.jupiter.api.BeforeEach;
9+
import com.syncapi.security.JwtUtil;
10+
import com.syncapi.service.auth.AuthService;
911
import org.junit.jupiter.api.Test;
1012
import org.junit.jupiter.params.ParameterizedTest;
1113
import org.junit.jupiter.params.provider.MethodSource;
1214
import org.springframework.beans.factory.annotation.Autowired;
1315
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
16+
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
1417
import org.springframework.http.MediaType;
18+
import org.springframework.test.context.bean.override.mockito.MockitoBean;
1519
import org.springframework.test.web.servlet.MockMvc;
1620
import org.springframework.test.web.servlet.ResultActions;
1721

1822
import java.util.stream.Stream;
1923

20-
import static com.syncapi.TestUtil.*;
21-
import static org.assertj.core.api.Assertions.assertThat;
24+
import static org.mockito.ArgumentMatchers.any;
25+
import static org.mockito.Mockito.*;
2226
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
2327

24-
@AutoConfigureMockMvc
25-
class AuthControllerTest extends AbstractIntegrationTest {
28+
@WebMvcTest(controllers = AuthController.class)
29+
@AutoConfigureMockMvc(addFilters = false)
30+
class AuthControllerTest {
2631
private static final String AUTH_URL = "/api/auth";
2732

2833
@Autowired
2934
private MockMvc mockMvc;
3035

31-
@Autowired
32-
private UserRepository userRepository;
36+
@MockitoBean
37+
private AuthService authService;
3338

34-
@BeforeEach
35-
void setUp() {
36-
userRepository.deleteAll();
37-
}
39+
// required as JwtAuthenticationFilter dependency
40+
@MockitoBean
41+
private JwtUtil jwtUtil;
42+
@MockitoBean
43+
private UserRepository userRepository;
3844

3945
@Test
4046
void shouldRegisterNewUser() throws Exception {
4147
// given
42-
String name = generateRandomName();
43-
String email = generateRandomEmail();
44-
RegisterRequest request = new RegisterRequest(name, email, generateRandomPassword());
48+
String name = TestUtil.generateRandomName();
49+
String email = TestUtil.generateRandomEmail();
50+
RegisterRequest request = new RegisterRequest(name, email, TestUtil.generateRandomPassword());
51+
52+
String token = TestUtil.generateRandomToken();
53+
AuthResponse response = new AuthResponse(token, email, name);
54+
55+
when(authService.register(any(RegisterRequest.class)))
56+
.thenReturn(response);
4557

4658
// when
47-
ResultActions res = mockMvc.perform(postJson(AUTH_URL + "/register", request));
59+
ResultActions res = mockMvc.perform(JsonTestUtil.postJson(AUTH_URL + "/register", request));
4860

4961
// then
5062
res.andExpect(status().isOk())
5163
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
52-
.andExpect(jsonPath("$.token").isString())
53-
.andExpect(jsonPath("$.token").isNotEmpty())
54-
.andExpect(jsonPath("$.email").value(email))
55-
.andExpect(jsonPath("$.name").value(name));
56-
57-
User user = userRepository.findByEmail(email).orElseThrow();
58-
assertThat(user.getName()).isEqualTo(name);
59-
assertThat(user.getPasswordHash()).isNotBlank();
64+
.andExpectAll(
65+
jsonPath("$.token").value(token),
66+
jsonPath("$.email").value(email),
67+
jsonPath("$.name").value(name)
68+
);
69+
70+
verify(authService).register(any(RegisterRequest.class));
6071
}
6172

6273
@Test
6374
void shouldFailWhenEmailAlreadyExists() throws Exception {
6475
// given
65-
String email = generateRandomEmail();
66-
RegisterRequest first = new RegisterRequest(generateRandomName(), email, generateRandomPassword());
67-
RegisterRequest second = new RegisterRequest(generateRandomName(), email, generateRandomPassword());
76+
RegisterRequest request = new RegisterRequest(
77+
TestUtil.generateRandomName(), TestUtil.generateRandomEmail(), TestUtil.generateRandomPassword()
78+
);
79+
80+
when(authService.register(any(RegisterRequest.class)))
81+
.thenThrow(new RuntimeException("email already exists"));
6882

6983
// when / then
70-
mockMvc.perform(postJson(AUTH_URL + "/register", first))
71-
.andExpect(status().isOk());
72-
mockMvc.perform(postJson(AUTH_URL + "/register", second))
84+
mockMvc.perform(JsonTestUtil.postJson(AUTH_URL + "/register", request))
7385
.andExpect(status().isBadRequest());
86+
87+
verify(authService).register(any(RegisterRequest.class));
7488
}
7589

7690
@ParameterizedTest(name = "[{index}] invalid register request -> 400")
7791
@MethodSource("invalidRegisterRequests")
7892
void shouldFailValidationForInvalidRegisterRequest(RegisterRequest request) throws Exception {
7993
// when / then
80-
mockMvc.perform(postJson(AUTH_URL + "/register", request))
94+
mockMvc.perform(JsonTestUtil.postJson(AUTH_URL + "/register", request))
8195
.andExpect(status().isBadRequest());
96+
97+
verifyNoInteractions(authService);
8298
}
8399

84100
private static Stream<RegisterRequest> invalidRegisterRequests() {
85101
return Stream.of(
86-
new RegisterRequest("", generateRandomEmail(), generateRandomPassword()), // blank name
87-
new RegisterRequest(null, generateRandomEmail(), generateRandomPassword()), // null name
88-
new RegisterRequest("John", "not-an-email", generateRandomPassword()), // invalid email
89-
new RegisterRequest("John", "", generateRandomPassword()), // blank email
90-
new RegisterRequest("John", generateRandomEmail(), "123") // short password
102+
new RegisterRequest("", TestUtil.generateRandomEmail(), TestUtil.generateRandomPassword()),
103+
new RegisterRequest(null, TestUtil.generateRandomEmail(), TestUtil.generateRandomPassword()),
104+
new RegisterRequest("John", "not-an-email", TestUtil.generateRandomPassword()),
105+
new RegisterRequest("John", "", TestUtil.generateRandomPassword()),
106+
new RegisterRequest("John", TestUtil.generateRandomEmail(), "123")
91107
);
92108
}
93109

94110
@Test
95111
void shouldLoginSuccessfully() throws Exception {
96112
// given
97-
String email = generateRandomEmail();
98-
String password = generateRandomPassword();
99-
RegisterRequest register = new RegisterRequest("Login User", email, password);
113+
String email = TestUtil.generateRandomEmail();
114+
String token = TestUtil.generateRandomToken();
100115

101-
mockMvc.perform(postJson(AUTH_URL + "/register", register))
102-
.andExpect(status().isOk());
116+
LoginRequest request = new LoginRequest(email, TestUtil.generateRandomPassword());
117+
AuthResponse response = new AuthResponse(token, email, TestUtil.generateRandomName());
103118

104-
LoginRequest login = new LoginRequest(email, password);
119+
when(authService.login(any(LoginRequest.class)))
120+
.thenReturn(response);
105121

106122
// when
107-
ResultActions res = mockMvc.perform(postJson(AUTH_URL + "/login", login));
123+
ResultActions res = mockMvc.perform(JsonTestUtil.postJson(AUTH_URL + "/login", request));
108124

109125
// then
110126
res.andExpect(status().isOk())
111127
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
112-
.andExpect(jsonPath("$.token").isString())
113-
.andExpect(jsonPath("$.token").isNotEmpty())
114-
.andExpect(jsonPath("$.email").value(email));
128+
.andExpectAll(
129+
jsonPath("$.token").value(token),
130+
jsonPath("$.email").value(email)
131+
);
132+
133+
verify(authService).login(any(LoginRequest.class));
115134
}
116135

117136
@ParameterizedTest(name = "[{index}] invalid login -> 400")
118137
@MethodSource("invalidLoginRequests")
119138
void shouldFailLoginForInvalidCredentials(LoginRequest request) throws Exception {
120-
// when / then
121-
mockMvc.perform(postJson(AUTH_URL + "/login", request))
139+
boolean passesValidation = request.getEmail() != null
140+
&& !request.getEmail().isBlank()
141+
&& request.getEmail().contains("@")
142+
&& request.getPassword() != null
143+
&& !request.getPassword().isBlank();
144+
if (passesValidation) {
145+
when(authService.login(any(LoginRequest.class)))
146+
.thenThrow(new RuntimeException("invalid credentials"));
147+
}
148+
149+
mockMvc.perform(JsonTestUtil.postJson(AUTH_URL + "/login", request))
122150
.andExpect(status().isBadRequest());
151+
152+
if (passesValidation) {
153+
verify(authService).login(any(LoginRequest.class));
154+
} else {
155+
verifyNoInteractions(authService);
156+
}
123157
}
124158

125159
private static Stream<LoginRequest> invalidLoginRequests() {
126160
return Stream.of(
127-
new LoginRequest("not-an-email", "password"), // invalid email
128-
new LoginRequest("", "password"), // blank email
129-
new LoginRequest(generateRandomEmail(), ""), // blank password
130-
new LoginRequest(generateRandomEmail(), "wrong-password") // wrong password
161+
new LoginRequest("not-an-email", "password"),
162+
new LoginRequest("", "password"),
163+
new LoginRequest(TestUtil.generateRandomEmail(), ""),
164+
new LoginRequest(TestUtil.generateRandomEmail(), "wrong-password")
131165
);
132166
}
133167
}

0 commit comments

Comments
 (0)