Etc

WebFlux 사양의 슬라이스 테스트

Jungsoomin :) 2021. 4. 15. 14:45
  • 컨트롤러 => @WebFluxTest
  • 서비스 => @Mock + WebEnvironment.NONE
  • 리포지토리 => @DataR2dbcTest

 

왜 하죠?

  • 테스트 구동마다 웹서버를 구동한다.
  • 테스트 구동마다 웹서버 구동에 필요한 모든 클래스를 컴파일한다.
  • 지침..

 

 

1. 컨트롤러

  1. 필요한 Bean => RouterFunction , Handler , 
  2. Mocking => Service
    1. 컨트롤러에 에러를 전파하고 싶을경우 => CorePublisher 구현체 .error() 사용
@WebFluxTest(RoleHandlerImpl.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // @Order 로 테스트 순서를 잡는다.
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Import({RoleRouter.class})
public class RoleControllerTests {
    private static final Logger LOGGER = LoggerFactory.getLogger(RoleControllerTests.class);
    @Autowired
    private WebTestClient client;

    @MockBean
    private RoleService roleService;


    private Role role;

    @BeforeAll
    public void setClientAndBean() {
        LOGGER.info("=====================Start Mocking Role ServiceImpl=====================");
        role = new Role();
        role.setId(1L);
        role.setRoleType("슈퍼관리자");
        role.setRemoved(false);
        
        Role role1 = new Role();
        role1.setId(2L);
        role1.setRoleType("관리자");
        role.setRemoved(false);

        Role role2 = new Role();
        role2.setId(3L);
        role2.setRoleType("일반사용자");
        role.setRemoved(false);
        Object mock = Mockito.when(roleService.processReadAll()).thenReturn(Mono.just(Arrays.asList(role, role1, role2))).getMock();
        LOGGER.info("Mocking Bean is : {} \n",mock.getClass().getSimpleName());
    }
    @AfterAll
    public void ln() {
        System.out.println();
    }

    @Test
    @Order(0)
    public void provideAllRolesTest() {
        LOGGER.info("===================== provideAllRolesTest > OK =====================");
        client.get().uri("/api/v1/role/read/all")
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isEqualTo(HttpStatus.OK)
                .expectHeader().contentType(MediaType.APPLICATION_JSON)
                .expectBodyList(Role.class)
                .value(roles -> LOGGER.warn("Http OK Status, ResponseBody is : {}\n",roles.get(0)))
                .value(roles -> assertThat(roles.get(0).getId(),Matchers.is(role.getId())))
                .value(roles -> assertThat(roles.size(), Matchers.is(3)));

        Mockito.when(roleService.processReadAll()).thenReturn(Mono.error(new RuntimeException("테스트익셉션")));

        LOGGER.info("===================== provideAllRolesTest > BAD_REQUEST =====================");
         client.get().uri("/api/v1/role/read/all")
                 .accept(MediaType.APPLICATION_JSON)
                 .exchange()
                 .expectStatus().isEqualTo(HttpStatus.BAD_REQUEST)
                 .expectBody(String.class).isEqualTo("테스트익셉션")
                 .value(s -> LOGGER.warn("Http BAD_REQUEST Status, ResponseBody is : {}",s));
    }

    @Test
    @Order(1)
    public void provideOneRolesTest() {


    }

}

 

 

2. 서비스

  1. @SpringBootTest => WebEnvironment.NONE 
  2. @Import => Service 구현체 , Repository 구현체
@SpringBootTest(properties = "spring.profiles.active=test",webEnvironment = SpringBootTest.WebEnvironment.NONE)
@Import({RoleServiceImpl.class, CustomRoleRepositoryImpl.class})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // @Order 로 테스트 순서를 잡는다.
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class RoleServiceTests {
    private static final Logger LOGGER = LoggerFactory.getLogger(RoleServiceTests.class);

    @Autowired
    DatabaseClient client;
    @Autowired
    private RoleService roleService;
    @Autowired
    private MemberRepository memberRepository;

    @BeforeAll
    public void createTables(){
        RoleRepositoryTests.createTable(client);
        MenuRepositoryTests.createTable(client);
        RoleRepositoryJoinTests.createMiddleTable(client);
        CustomMemberRepositoryImplTest.createTable(client);
    }

    @AfterEach
    public void ln() {
        System.out.println();
    }

    @Test
    @Order(1)
    public void processReadAllTest() {
        LOGGER.info("=====================ProcessReadAllTest=====================");
        List<Role> result = roleService.processReadAll().block();

        assertThat(result, Matchers.notNullValue());
        assertThat(result.size(),is(3));
    }

    @Test
    @Order(2)
    public void processReadOneTest() {
        LOGGER.info("=====================processReadOneTest=====================");
        Role result = roleService.processReadOne(1L).block();

        assertThat(result,Matchers.notNullValue());
        assertThat(result.getId(),is(1L));
        assertThat(result.getRoleType(),is("슈퍼관리자"));
    }

    @Test
    @Order(3)
    public void processCreateOneTest() {
        LOGGER.info("=====================processCreateOneTest=====================");
        Role role = new Role();
        role.setRoleType("서비스레이어 테스트");

        Long result = roleService.processCreateOne(role).block();
        assertThat(result, is(4L));

        role.setRoleType("서비스레이어 테스트");
        StepVerifier.create(roleService.processCreateOne(role)).expectErrorMatches(throwable ->
                throwable instanceof UnProcessableEntityException);
    }

    @Test
    @Order(4)
    public void processUpdateOneTest() {
        LOGGER.info("=====================processUpdateOneTest=====================");
        Role foundRole = roleService.processReadOne(1L).block();

        foundRole.setRemoved(true);
        Integer resultRow = roleService.processUpdateOne(foundRole).block();
        foundRole = roleService.processReadOne(1L).block();
        assertThat(resultRow,is(1));
        assertThat(foundRole.isRemoved(),is(true));
    }

    @Test
    @Order(5)
    public void processDeleteOneTest() {
        LOGGER.info("=====================processDeleteOneTest=====================");
        Integer resultRow = roleService.processDeleteOne(1L).block();

        assertThat(resultRow, is(1));

        List<Member> confirmList = memberRepository.selectAll().collectList().block();
        assertThat(confirmList.size(), is(2));
        List<Map<String, Object>> confirmMiddle = client.sql("select * from role_menu").fetch().all().log().collectList().block();
        assertThat(confirmMiddle, Matchers.empty());

        Integer result = roleService.processDeleteOne(6L).block();
        assertThat(result,is(0));
    }

    @Test
    @Order(6)
    public void processDeleteAllTest() {
        LOGGER.info("=====================processDeleteAllTest=====================");
        Integer result = roleService.processDeleteAll().block();

        assertThat(result, is(3));

        List<Role> roles = roleService.processReadAll().block();

        assertThat(roles.size(),is(0));

        LOGGER.warn("Entity Check");
        LOGGER.warn("Empty List ? => {}",roles.isEmpty());
    }

}

 

 

3. 리포지토리

  1. @DataR2dbcTest => properties 는 H2ConnectionFactory 빈 생성으로 줌
@DataR2dbcTest(properties = "spring.profiles.active=test")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // @Order 로 테스트 순서를 잡는다.
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class RoleRepositoryTests {
    private static final Logger LOGGER = LoggerFactory.getLogger(RoleRepositoryTests.class);

    @Autowired
    private DatabaseClient client;
    @Autowired
    private RoleRepository roleRepository;


    public static void createTable(DatabaseClient client) {
        System.out.println("=====================Start Create Role Table=====================");
        client.sql("create table role (\n" +
                "    role_id int8 AUTO_INCREMENT primary key ,\n" +
                "    role_name varchar(255) unique ,\n" +
                "    is_removed boolean default false\n" +
                ")")
                .fetch().all().log().collectList().block();
        client.sql("insert into role (role_name) VALUES (:role_name)").bind("role_name","슈퍼관리자").fetch().rowsUpdated().block();
        client.sql("insert into role (role_name) VALUES (:role_name)").bind("role_name","관리자").fetch().rowsUpdated().block();
        client.sql("insert into role (role_name) VALUES (:role_name)").bind("role_name","일반사용자").fetch().rowsUpdated().block();
        System.out.println("=====================Completed Create Role Table=====================\n");
    }

    @BeforeAll
    public void insertRecord() {
        createTable(client);
    }

    @AfterEach
    public void ln() {
        System.out.println();
    }

    @Test
    @Order(0)
    public void SelectAllTest() {
        LOGGER.info("=====================SelectAllTest=====================");
        List<Role> roles = roleRepository.selectAll().collectList().block();

        assertThat(roles, Matchers.notNullValue());
        roles.forEach(System.out::println);
    }

    @Test
    @Order(1)
    public void selectOneTest() {
        LOGGER.info("=====================selectOneTest=====================");
        Role roleByOne = roleRepository.selectById(1L).block();
        assertThat(roleByOne.getId(), is(1L));
    }

    @Test
    @Order(2)
    public void insertOneTest() {
        LOGGER.info("=====================insertOneTest=====================");
        Role role = new Role();
        role.setRoleType("샘플");

        Long gId = roleRepository.create(role).block();
        assertThat(gId,is(4L));

        Role foundRole = roleRepository.selectById(gId).block();
        assertThat(foundRole.getId(),is(4L));
    }

    @Test
    @Order(3)
    public void updateOneTest() {
        LOGGER.info("=====================updateOneTest=====================");
        Role foundOne = roleRepository.selectById(1L).block();
        assertThat(foundOne.getId(),is(1L));
        assertThat(foundOne.getRoleType(),is("슈퍼관리자"));

        foundOne.setRemoved(true);

        roleRepository.update(foundOne).block();
        foundOne = roleRepository.selectById(1L).block();

        assertThat(foundOne.isRemoved(),is(true));
    }

    @Test
    @Order(4)
    public void deleteOneTest() {
        LOGGER.info("=====================deleteOneTest=====================");
        Integer deleteRowId = roleRepository.deleteOneById(1L).block();
        assertThat(deleteRowId, is(1));

        Long rowCount = roleRepository.selectAll().count().block();
        assertThat(rowCount, is(3L ));
    }

    @Test
    @Order(5)
    public void deleteAllTest() {
        LOGGER.info("=====================deleteAllTest=====================");
        Integer deletedRow = roleRepository.deleteAllRecord().block();
        assertThat(deletedRow,is(3));
    }

}