관리 메뉴

bright jazz music

blog 31 : 세션 토큰 발급기능 추가 1 본문

Projects/blog

blog 31 : 세션 토큰 발급기능 추가 1

bright jazz music 2023. 2. 15. 07:37

로그인 할 때 세션 토큰을 발급하여 인증에 사용할 수 있도록 개선한다.

 

1. AuthService 생성 및 AuthController 수정

여기서 로그인 및 토큰 발급처리를 진행한다.

//AuthService.java

package com.endofma.blog.service;

import com.endofma.blog.domain.User;
import com.endofma.blog.exception.InvalidSigninInformation;
import com.endofma.blog.repository.UserRepository;
import com.endofma.blog.request.Login;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;

@Service
@RequiredArgsConstructor
public class AuthService {

    private final UserRepository userRepository;

    @Transactional
    public void signin(Login login){
        User user = userRepository.findByEmailAndPassword(login.getEmail(), login.getPassword())
                .orElseThrow(InvalidSigninInformation::new);
    }
}

 

 

AuthController에 들어 있던 DB조회 코드를 Service쪽으로 분리하였다.

 

//AuthController.java


@Slf4j
@RestController
@RequiredArgsConstructor
public class AuthController {

    //생성자를 통한 주입
    //private final UserRepository userRepository;
    //로그인 및 인증 절차를 서비스에 위임
    private final AuthService authService;

    @PostMapping("/auth/login")
    public void login(@RequestBody Login login){

        //json ID/PW
        log.info(">>> login = {}", login.toString());

        //DB에서 조회
        //User user = userRepository.findByEmailAndPassword(login.getEmail(), login.getPassword())
        //             .orElseThrow(InvalidSigninInformation::new);

        authService.signin(login);

    }
}

 

요청 테스트

### auth.http

POST http://localhost:8080/auth/login
Content-Type: application/json

{
  "email" : "catnails@gmail.com",
  "password" : "1234"
}

 

 

 

 

 

2. Session으로 사용할 클래스를 생성하고 User와 연관관계 맺어주기

//Session.java
package com.endofma.blog.domain;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Session {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String accessToken;
}

 

 

초기 생성된 모습은 위와 같다. 이를  User와 연관관계 맺어야 한다.

또한 토큰 발급 코드 역시 추가해준다.

 

 

//Session.java

package com.endofma.blog.domain;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.UUID;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Session {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String accessToken;

    //연관관계 맺기
    @ManyToOne //세션 여러 개가 하나의 유저에 속할 수 있다.
    private User user;
    
    //토큰 발급
    //세션을 넣어주기 위해서 빌더 패턴으로 생성자 생성(일반 생성자로 해도 됨)
    @Builder 
    public Session(User user) {
        this.accessToken = UUID.randomUUID().toString(); 
        this.user = user;
    }
}

 

 

//User.java

package com.endofma.blog.domain;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name="users") //테이블 명 설정 user는 예약어라 오류발생
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String email;

    private String password;

    private LocalDateTime createdAt;

    //연관관계 맺기
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user") //한 명의 유저가 여러 세션을 가질 수 있기 때문에 OneToMany
    private List<Session> sessions = new ArrayList<>();
    
    public void addSession() {
        sessions.add(Session.builder()
                .user(this)
                .build());
    }
}

 

3. 로그인이 성공인 경우에 토큰을 발급하는 코드를 AuthService에 작성하기

//AuthService.java

package com.endofma.blog.service;

import com.endofma.blog.domain.User;
import com.endofma.blog.exception.InvalidSigninInformation;
import com.endofma.blog.repository.UserRepository;
import com.endofma.blog.request.Login;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;

@Service
@RequiredArgsConstructor
public class AuthService {

    private final UserRepository userRepository;

    @Transactional
    public void signin(Login login){
        User user = userRepository.findByEmailAndPassword(login.getEmail(), login.getPassword())
                .orElseThrow(InvalidSigninInformation::new);

        //세션 발급
        user.addSession();
    }
}

 

4. 테스트를 수행하기 위해 Session.java와 User.java 코드 수정

둘 다 빌더가 추가되었다. @Getter도 추가

//Session.java
package com.endofma.blog.domain;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.UUID;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Session {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String accessToken;

    //연관관계 맺기
    @ManyToOne //세션 여러 개가 하나의 유저에 속할 수 있다.
    private User user;

    @Builder //세션을 넣어주기 위해서 빌더 패턴으로 생성자 생성
    public Session(User user) {
        this.accessToken = UUID.randomUUID().toString();
        this.user = user;
    }
}

 

//User.java

package com.endofma.blog.domain;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name="users") //테이블 명 설정 user는 예약어라 오류발생
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String email;

    private String password;

    private LocalDateTime createdAt;

    //연관관계 맺기
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user") //한 명의 유저가 여러 세션을 가질 수 있기 때문에 OneToMany
    private List<Session> sessions = new ArrayList<>();

    @Builder
    public User(String name, String email, String password){
        this.name = name;
        this.email = email;
        this. password = password;
        this.createdAt = LocalDateTime.now(); //정책상 가입하여 생성된 시간을 넣어준다.
        //세션은 넣지 않는다. 가입을 한다고 해서 세션을 추가해 줄 필요는 없다.
    }

    public void addSession() {
        sessions.add(Session.builder()
                .user(this)
                .build());
    }
}

 

5. SessionRepository.java 생성

package com.endofma.blog.repository;

import com.endofma.blog.domain.Session;
import org.springframework.data.repository.CrudRepository;

public interface SessionRepository extends CrudRepository<Session, Long> {
}

 

6. 테스트 수행 : AuthControllerTest.java

package com.endofma.blog.controller;

import com.endofma.blog.domain.User;
import com.endofma.blog.repository.SessionRepository;
import com.endofma.blog.repository.UserRepository;
import com.endofma.blog.request.Login;
import com.endofma.blog.request.PostCreate;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.juli.logging.Log;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
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.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import javax.print.attribute.standard.Media;
import javax.transaction.Transactional;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
public class AuthControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private SessionRepository sessionRepository;

    @BeforeEach
    void clean(){
    userRepository.deleteAll();
    }

    @Test
    @DisplayName("로그인 성공 ")
    void test1() throws Exception {
        //given
        //테스트에서는 data.sql이 실행되지 않으므로, 또 실행된다고 해도 테스트와 독립된 것이 권장되므로 값을 넣어준다.
        userRepository.save(User.builder()
                .name("catnails")
                .email("catnails@gmail.com")
                .password("1234") //추후 scrypt, bcrypt 적용
                .build());

        Login login = Login.builder()
                .email("catnails@gmail.com")
                .password("1234")
                .build();

        String json = objectMapper.writeValueAsString(login);

        //expected
        mockMvc.perform(post("/auth/login")
                .contentType(MediaType.APPLICATION_JSON)
                .content(json))
                .andExpect(status().isOk())
                .andDo(print());

    }
    @Test
    @Transactional
    @DisplayName("로그인 성공 후 세션 추가")
    void test2() throws Exception {
        //given
        User user = userRepository.save(User.builder()
                .name("catnails")
                .email("catnails@gmail.com")
                .password("1234") //추후 scrypt, bcrypt 적용
                .build());

        Login login = Login.builder()
                .email("catnails@gmail.com")
                .password("1234")
                .build();

        String json = objectMapper.writeValueAsString(login);

        //expected
        mockMvc.perform(post("/auth/login")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(json))
                .andExpect(status().isOk())
                .andDo(print());

        User loggedInUser = userRepository.findById(user.getId())
                        .orElseThrow(RuntimeException::new);

        Assertions.assertEquals(1L, user.getSessions().size());

    }


}

 

User객체에 세션이 들어와 있는 것을 확인할 수 있다.

 

결과

 

.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.6)

2023-02-15 22:29:01.960  INFO 14908 --- [    Test worker] c.e.blog.controller.AuthControllerTest   : Starting AuthControllerTest using Java 11.0.12 on DESKTOP-Q7HBM41 with PID 14908 (started by user in D:\personal\blog)
2023-02-15 22:29:01.964  INFO 14908 --- [    Test worker] c.e.blog.controller.AuthControllerTest   : No active profile set, falling back to 1 default profile: "default"
2023-02-15 22:29:03.112  INFO 14908 --- [    Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2023-02-15 22:29:03.238  INFO 14908 --- [    Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 110 ms. Found 3 JPA repository interfaces.
2023-02-15 22:29:04.090  INFO 14908 --- [    Test worker] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-02-15 22:29:04.433  INFO 14908 --- [    Test worker] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2023-02-15 22:29:04.557  INFO 14908 --- [    Test worker] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2023-02-15 22:29:04.644  INFO 14908 --- [    Test worker] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.6.14.Final
2023-02-15 22:29:05.029  INFO 14908 --- [    Test worker] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2023-02-15 22:29:05.255  INFO 14908 --- [    Test worker] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2023-02-15 22:29:06.367  INFO 14908 --- [    Test worker] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2023-02-15 22:29:06.381  INFO 14908 --- [    Test worker] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2023-02-15 22:29:07.569  WARN 14908 --- [    Test worker] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2023-02-15 22:29:08.105  INFO 14908 --- [    Test worker] o.s.b.a.h2.H2ConsoleAutoConfiguration    : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:blog'
2023-02-15 22:29:08.716  INFO 14908 --- [    Test worker] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
2023-02-15 22:29:08.716  INFO 14908 --- [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : Initializing Servlet ''
2023-02-15 22:29:08.718  INFO 14908 --- [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : Completed initialization in 2 ms
2023-02-15 22:29:08.752  INFO 14908 --- [    Test worker] c.e.blog.controller.AuthControllerTest   : Started AuthControllerTest in 7.485 seconds (JVM running for 11.274)
2023-02-15 22:29:08.807  INFO 14908 --- [    Test worker] o.s.t.c.transaction.TransactionContext   : Began transaction (1) for test context [DefaultTestContext@64d7b720 testClass = AuthControllerTest, testInstance = com.endofma.blog.controller.AuthControllerTest@3a2881d6, testMethod = test2@AuthControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@30272916 testClass = AuthControllerTest, locations = '{}', classes = '{class com.endofma.blog.BlogApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@51cd7ffc, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@4b3fa0b3, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@160ac7fb, [ImportsContextCustomizer@5bb3d42d key = [org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityConfiguration, org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@2dbe250d, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@4f071df8, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@2f9a01c1, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@26adfd2d], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@2a7b4bb6]; rollback [true]
2023-02-15 22:29:09.419  INFO 14908 --- [    Test worker] c.e.blog.controller.AuthController       : >>> login = Login(email=catnails@gmail.com, password=1234)

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /auth/login
       Parameters = {}
          Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"48"]
             Body = {"email":"catnails@gmail.com","password":"1234"}
    Session Attrs = {}

Handler:
             Type = com.endofma.blog.controller.AuthController
           Method = com.endofma.blog.controller.AuthController#login(Login)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = []
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []
2023-02-15 22:31:14.094  WARN 14908 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=2m9s559ms79µs400ns).
2023-02-15 22:31:14.113  INFO 14908 --- [    Test worker] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test: [DefaultTestContext@64d7b720 testClass = AuthControllerTest, testInstance = com.endofma.blog.controller.AuthControllerTest@3a2881d6, testMethod = test2@AuthControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@30272916 testClass = AuthControllerTest, locations = '{}', classes = '{class com.endofma.blog.BlogApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@51cd7ffc, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@4b3fa0b3, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@160ac7fb, [ImportsContextCustomizer@5bb3d42d key = [org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityConfiguration, org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@2dbe250d, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@4f071df8, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@2f9a01c1, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@26adfd2d], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]
2023-02-15 22:31:14.144  INFO 14908 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-02-15 22:31:14.144  INFO 14908 --- [ionShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'
2023-02-15 22:31:14.149  WARN 14908 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 90121, SQLState: 90121
2023-02-15 22:31:14.149 ERROR 14908 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper   : Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214]
2023-02-15 22:31:14.150  WARN 14908 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 90121, SQLState: 90121
2023-02-15 22:31:14.150 ERROR 14908 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper   : Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214]
2023-02-15 22:31:14.151  WARN 14908 --- [ionShutdownHook] o.s.b.f.support.DisposableBeanAdapter    : Invocation of destroy method failed on bean with name 'entityManagerFactory': org.hibernate.exception.JDBCConnectionException: Unable to release JDBC Connection used for DDL execution
2023-02-15 22:31:14.151  INFO 14908 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2023-02-15 22:31:14.158  INFO 14908 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
Disconnected from the target VM, address: 'localhost:52846', transport: 'socket'
BUILD SUCCESSFUL in 2m 18s
5 actionable tasks: 1 executed, 4 up-to-date
PM 10:31:14: Execution finished ':test --tests "com.endofma.blog.controller.AuthControllerTest.test2"'.

 

 

 

 

 

 

 

 

Comments