Skip to content

Commit

Permalink
Merge pull request #62 from Arquisoft/test/login
Browse files Browse the repository at this point in the history
Added tests for the Authentication endpoints
  • Loading branch information
Toto-hitori authored Mar 1, 2024
2 parents ec2bf05 + 4c2c993 commit 619d2f8
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 10 deletions.
5 changes: 5 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion api/src/main/java/lab/en2b/quizapi/auth/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
@Service
@RequiredArgsConstructor
public class AuthService {
private final JwtUtils jwtUtils;
private final AuthenticationManager authenticationManager;
private final UserService userService;
private final JwtUtils jwtUtils;
/**
* Creates a session for a user. Throws an 401 unauthorized exception otherwise
* @param loginRequest the request containing the login info
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package lab.en2b.quizapi.auth.dtos;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.*;

import java.util.List;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
@EqualsAndHashCode
public class JwtResponseDto {
private String token;
@JsonProperty("refresh_token")
Expand Down
5 changes: 5 additions & 0 deletions api/src/main/java/lab/en2b/quizapi/auth/dtos/LoginDto.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package lab.en2b.quizapi.auth.dtos;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand All @@ -10,7 +12,10 @@
@Data
public class LoginDto {
@NonNull
@NotBlank
@Email
private String email;
@NonNull
@NotBlank
private String password;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lab.en2b.quizapi.auth.dtos;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand All @@ -10,7 +11,8 @@
@NoArgsConstructor
@Data
public class RefreshTokenDto {
@NonNull
@JsonProperty("refresh_token")
@NonNull
@NotEmpty
private String refreshToken;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package lab.en2b.quizapi.auth.dtos;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.*;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class RefreshTokenResponseDto {

private String token;
Expand Down
6 changes: 6 additions & 0 deletions api/src/main/java/lab/en2b/quizapi/auth/dtos/RegisterDto.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package lab.en2b.quizapi.auth.dtos;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand All @@ -9,10 +11,14 @@
@NoArgsConstructor
@Data
public class RegisterDto {
@NotBlank
@NonNull
@Email
private String email;
@NonNull
@NotBlank
private String username;
@NonNull
@NotBlank
private String password;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class UserService implements UserDetailsService {
private final UserRepository userRepository;
private final RoleRepository roleRepository;
@Value("${REFRESH_TOKEN_DURATION_MS}")
private Long REFRESH_TOKEN_DURATION_MS;
private long REFRESH_TOKEN_DURATION_MS;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
return UserDetailsImpl.build(userRepository.findByEmail(email).orElseThrow());
Expand Down
13 changes: 13 additions & 0 deletions api/src/main/java/lab/en2b/quizapi/commons/utils/TestUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package lab.en2b.quizapi.commons.utils;

import com.fasterxml.jackson.databind.ObjectMapper;

public class TestUtils {
public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
137 changes: 137 additions & 0 deletions api/src/test/java/lab/en2b/quizapi/auth/AuthControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package lab.en2b.quizapi.auth;

import lab.en2b.quizapi.auth.config.SecurityConfig;
import lab.en2b.quizapi.auth.dtos.LoginDto;
import lab.en2b.quizapi.auth.dtos.RefreshTokenDto;
import lab.en2b.quizapi.auth.dtos.RegisterDto;
import lab.en2b.quizapi.auth.jwt.JwtUtils;
import lab.en2b.quizapi.commons.user.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.ResponseEntity;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultMatcher;

import static lab.en2b.quizapi.commons.utils.TestUtils.asJsonString;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(AuthController.class)
@AutoConfigureMockMvc
@Import(SecurityConfig.class)
public class AuthControllerTest {
@Autowired
MockMvc mockMvc;
@MockBean
AuthService authService;
@MockBean
JwtUtils jwtUtils;
@MockBean
UserService userService;
@Test
void registerUserShouldReturn200() throws Exception {
when(authService.register(any())).thenReturn(ResponseEntity.ok().build());
testRegister(asJsonString( new RegisterDto("[email protected]","test","testing"))
,status().isOk());
}
@Test
void registerEmptyBodyShouldReturn400() throws Exception {
testRegister("{}",status().isBadRequest());
}
@Test
void registerEmptyEmailShouldReturn400() throws Exception {
testRegister(asJsonString( new RegisterDto("","test","testing")),
status().isBadRequest());
}

@Test
void registerInvalidEmailShouldReturn400() throws Exception {
testRegister(asJsonString( new RegisterDto("iAmAnInvalidEmail","test","testing")),
status().isBadRequest());
}

@Test
void registerEmptyUsernameShouldReturn400() throws Exception {
testRegister(asJsonString( new RegisterDto("[email protected]","","testing")),
status().isBadRequest());
}

@Test
void registerEmptyPasswordShouldReturn400() throws Exception {
testRegister(asJsonString( new RegisterDto("[email protected]","test","")),
status().isBadRequest());
}

@Test
void loginUserShouldReturn200() throws Exception {
when(authService.login(any())).thenReturn(ResponseEntity.ok().build());
testLogin(asJsonString( new LoginDto("[email protected]","password"))
,status().isOk());
}

@Test
void loginEmptyBodyShouldReturn400() throws Exception {
testLogin("{}",status().isBadRequest());
}
@Test
void loginEmptyEmailShouldReturn400() throws Exception {
testLogin(asJsonString( new LoginDto("","password")),
status().isBadRequest());
}

@Test
void loginInvalidEmailShouldReturn400() throws Exception {
testLogin(asJsonString( new LoginDto("iAmAnInvalidEmail","password")),
status().isBadRequest());
}

@Test
void refreshTokenShouldReturn200() throws Exception {
when(authService.refreshToken(any())).thenReturn(ResponseEntity.ok().build());
testRefreshToken(asJsonString( new RefreshTokenDto("58ca95e9-c4ef-45fd-93cf-55c040aaff9c"))
,status().isOk());
}

@Test
void refreshTokenEmptyBodyShouldReturn400() throws Exception {
when(authService.refreshToken(any())).thenReturn(ResponseEntity.ok().build());
testRefreshToken("{}",status().isBadRequest());
}

@Test
void refreshTokenEmptyTokenShouldReturn400() throws Exception {
when(authService.refreshToken(any())).thenReturn(ResponseEntity.ok().build());
testRefreshToken(asJsonString( new RefreshTokenDto("")), status().isBadRequest());
}

private void testRegister(String content, ResultMatcher code) throws Exception {
mockMvc.perform(post("/auth/register")
.content(content)
.contentType("application/json")
.with(csrf()))
.andExpect(code);
}

private void testLogin(String content, ResultMatcher code) throws Exception {
mockMvc.perform(post("/auth/login")
.content(content)
.contentType("application/json")
.with(csrf()))
.andExpect(code);
}

private void testRefreshToken(String content, ResultMatcher code) throws Exception {
mockMvc.perform(post("/auth/refresh-token")
.content(content)
.contentType("application/json")
.with(csrf()))
.andExpect(code);
}
}
111 changes: 111 additions & 0 deletions api/src/test/java/lab/en2b/quizapi/auth/AuthServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package lab.en2b.quizapi.auth;

import ch.qos.logback.core.util.TimeUtil;
import lab.en2b.quizapi.auth.config.UserDetailsImpl;
import lab.en2b.quizapi.auth.dtos.*;
import lab.en2b.quizapi.auth.jwt.JwtUtils;
import lab.en2b.quizapi.commons.user.User;
import lab.en2b.quizapi.commons.user.UserRepository;
import lab.en2b.quizapi.commons.user.UserService;
import lab.en2b.quizapi.commons.user.role.Role;
import lab.en2b.quizapi.commons.user.role.RoleRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import javax.swing.text.html.Option;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@ExtendWith({MockitoExtension.class, SpringExtension.class})
public class AuthServiceTest {
@InjectMocks
AuthService authService;
@Mock
UserService userService;
@Mock
UserRepository userRepository;
@Mock
RoleRepository roleRepository;
@Mock
AuthenticationManager authenticationManager;
@Mock
JwtUtils jwtUtils;
User defaultUser;
@BeforeEach
void setUp() {
this.userService = new UserService(userRepository,roleRepository);
this.authService = new AuthService(authenticationManager,userService,jwtUtils);
this.defaultUser = User.builder()
.id(1L)
.email("[email protected]")
.username("test")
.roles(Set.of(new Role("user")))
.password("password")
.refreshToken("token")
.refreshExpiration(Instant.ofEpochSecond(TimeUtil.computeStartOfNextSecond(System.currentTimeMillis()+ 1000)))
.build();
}
@Test
void testLogin(){
Authentication authentication = mock(Authentication.class);

when(authenticationManager.authenticate(any())).thenReturn(authentication);
when(authentication.getPrincipal()).thenReturn(UserDetailsImpl.build(defaultUser));
when(jwtUtils.generateJwtTokenUserPassword(authentication)).thenReturn("jwtToken");
when(userRepository.findById(any())).thenReturn(Optional.of(defaultUser));

ResponseEntity<JwtResponseDto> actual = authService.login(new LoginDto("test","password"));

assertEquals(ResponseEntity.of(Optional.of(
JwtResponseDto.builder()
.userId(1L)
.username(defaultUser.getUsername())
.email(defaultUser.getEmail())
.refreshToken(defaultUser.getRefreshToken())
.token("jwtToken")
.roles(List.of("user"))
.build()))
,actual);

}
@Test
void testRegister(){

when(userRepository.existsByEmail(any())).thenReturn(false);
when(userRepository.existsByUsername(any())).thenReturn(false);
when(userRepository.save(any())).thenAnswer(i -> i.getArguments()[0]);
when(roleRepository.findByName(any())).thenReturn(Optional.of(new Role("user")));

ResponseEntity<?> actual = authService.register(new RegisterDto("test","username","password"));

assertEquals(ResponseEntity.of(Optional.of("User registered successfully!")),actual);

}

@Test
void testRefreshToken(){

when(userRepository.findByRefreshToken(any())).thenReturn(Optional.of(defaultUser));
when(jwtUtils.generateTokenFromEmail(any())).thenReturn("jwtToken");

ResponseEntity<?> actual = authService.refreshToken(new RefreshTokenDto("token"));

assertEquals(ResponseEntity.of(Optional.of(new RefreshTokenResponseDto("jwtToken","token"))),actual);

}
}

0 comments on commit 619d2f8

Please sign in to comment.