diff --git a/instagram-adapter/build.gradle b/instagram-adapter/build.gradle index cd7eb08..e46b45e 100644 --- a/instagram-adapter/build.gradle +++ b/instagram-adapter/build.gradle @@ -1,11 +1,12 @@ dependencies { - implementation project(':instagram-data') + api project(':instagram-data') api project(':instagram-application') implementation group: 'com.maxmind.geoip2', name: 'geoip2', version: '2.3.1' implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-aws', version: '2.0.1.RELEASE' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '1.2.0.RELEASE' + testImplementation 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/instagram-adapter/src/test/java/clone/instagram/TestApplication.java b/instagram-adapter/src/test/java/clone/instagram/TestApplication.java new file mode 100644 index 0000000..20cace0 --- /dev/null +++ b/instagram-adapter/src/test/java/clone/instagram/TestApplication.java @@ -0,0 +1,8 @@ +package clone.instagram; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TestApplication { + +} diff --git a/instagram-adapter/src/test/java/clone/instagram/member/out/adapter/MemberPersistentAdapterTest.java b/instagram-adapter/src/test/java/clone/instagram/member/out/adapter/MemberPersistentAdapterTest.java new file mode 100644 index 0000000..ede58cd --- /dev/null +++ b/instagram-adapter/src/test/java/clone/instagram/member/out/adapter/MemberPersistentAdapterTest.java @@ -0,0 +1,57 @@ +package clone.instagram.member.out.adapter; + +import static org.assertj.core.api.Assertions.*; + +import org.assertj.core.api.ThrowableAssert; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; + +import clone.instagram.error.exception.member.MemberNotFoundException; +import clone.instagram.jpa.mapper.ImageMapper; +import clone.instagram.jpa.mapper.MemberMapper; +import clone.instagram.member.Member; + +@DataJpaTest +@Import({ImageMapper.class, MemberMapper.class, MemberPersistentAdapter.class}) +public class MemberPersistentAdapterTest { + + @Autowired + private MemberPersistentAdapter memberPersistentAdapter; + + @Nested + @DisplayName("loadMemberByUsername()") + class LoadMemberByUsername { + + @Test + @Sql("classpath:BaseMember.sql") + void validArguments_ReturnMember() { + // given + + // when + final Member member = memberPersistentAdapter.loadMemberByUsername("agent_username"); + + // then + assertThat(member.getUsername()).isEqualTo("agent_username"); + } + + @Test + @Sql("classpath:BaseMember.sql") + void usernameNotFound_ThrowException() { + // given + + // when + final ThrowableAssert.ThrowingCallable executable = + () -> memberPersistentAdapter.loadMemberByUsername("no_username"); + + // then + assertThatThrownBy(executable).isInstanceOf(MemberNotFoundException.class); + } + + } + +} diff --git a/instagram-adapter/src/test/resources/BaseMember.sql b/instagram-adapter/src/test/resources/BaseMember.sql new file mode 100644 index 0000000..b858a4c --- /dev/null +++ b/instagram-adapter/src/test/resources/BaseMember.sql @@ -0,0 +1,5 @@ +insert into members(username, password, name, email, gender, introduce, phone, website, image_name, image_type, image_uuid, image_url) + values('agent_username', 'password', 'agent_name', 'agent@email.com', 'PRIVATE', 'introduce', 'phone', 'website', 'image_name', 'PNG', 'image_uuid', 'image_url'); + +insert into members(username, password, name, email, gender, introduce, phone, website, image_name, image_type, image_uuid, image_url) +values('target_username', 'password', 'target_name', 'target@email.com', 'PRIVATE', 'introduce', 'phone', 'website', 'image_name', 'PNG', 'image_uuid', 'image_url'); \ No newline at end of file diff --git a/instagram-api/build.gradle b/instagram-api/build.gradle index d29aeac..55d14ed 100644 --- a/instagram-api/build.gradle +++ b/instagram-api/build.gradle @@ -10,4 +10,9 @@ dependencies { implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2' implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.2' implementation 'org.springframework.boot:spring-boot-starter-websocket' + + testImplementation 'com.h2database:h2' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testCompileOnly 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' } diff --git a/instagram-api/src/test/java/clone/instagram/member/controller/RegisterControllerTest.java b/instagram-api/src/test/java/clone/instagram/member/controller/RegisterControllerTest.java new file mode 100644 index 0000000..eb6656c --- /dev/null +++ b/instagram-api/src/test/java/clone/instagram/member/controller/RegisterControllerTest.java @@ -0,0 +1,47 @@ +package clone.instagram.member.controller; + +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import clone.instagram.member.BaseMemberImageProperty; +import clone.instagram.member.port.in.RegisterUseCase; + +@WebMvcTest(controllers = RegisterController.class) +public class RegisterControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private RegisterUseCase registerUseCase; + + @MockBean + private BaseMemberImageProperty baseMemberImageProperty; + + @Test + void validArguments_Invoke() throws Exception { + // given + final String request = "{" + + "\"username\":\"agent\", \"name\":\"name\", \"password\":\"password\", \"email\":\"agent@email.com\"" + + "}"; + given(registerUseCase.invoke(any())).willReturn(true); + + // when + mockMvc.perform(MockMvcRequestBuilders.post("/accounts") + .content(request) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isCreated()); + + // then + then(registerUseCase).should().invoke(any()); + } + +} diff --git a/instagram-application/build.gradle b/instagram-application/build.gradle index 98603ff..f77a784 100644 --- a/instagram-application/build.gradle +++ b/instagram-application/build.gradle @@ -3,6 +3,7 @@ dependencies { api project(':instagram-domain') implementation 'org.springframework.boot:spring-boot-starter-websocket' + testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.bootJar { enabled = false } diff --git a/instagram-application/src/test/java/clone/instagram/member/service/RegisterServiceTest.java b/instagram-application/src/test/java/clone/instagram/member/service/RegisterServiceTest.java new file mode 100644 index 0000000..151797f --- /dev/null +++ b/instagram-application/src/test/java/clone/instagram/member/service/RegisterServiceTest.java @@ -0,0 +1,68 @@ +package clone.instagram.member.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +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 clone.instagram.error.exception.member.UsernameAlreadyExistException; +import clone.instagram.member.BaseMemberImageProperty; +import clone.instagram.member.port.in.RegisterUseCase; +import clone.instagram.member.port.out.LoadMemberByUsernamePort; +import clone.instagram.member.port.out.SaveMemberPort; + +@ExtendWith(MockitoExtension.class) +public class RegisterServiceTest { + + @InjectMocks + private RegisterService registerService; + + @Mock + private LoadMemberByUsernamePort loadMemberPort; + + @Mock + private SaveMemberPort saveMemberPort; + + @Mock + private BaseMemberImageProperty baseMemberImageProperty; + + @Test + void validArguments_CallSaveMember() { + // given + final String username = "username"; + final RegisterUseCase.Command.ToRegisterInfo command + = new RegisterUseCase.Command.ToRegisterInfo( + username, "password", "name", "email", baseMemberImageProperty + ); + + // when + final boolean result = registerService.invoke(command); + + // then + then(saveMemberPort).should().saveMember(any()); + assertThat(result).isTrue(); + } + + @Test + void usernameExists_ThrowException() { + // given + final String username = "username"; + final RegisterUseCase.Command.ToRegisterInfo command + = new RegisterUseCase.Command.ToRegisterInfo( + username, "password", "name", "email", baseMemberImageProperty + ); + given(loadMemberPort.existsMemberByUsername(username)).willReturn(true); + + // when + final ThrowingCallable executable = () -> registerService.invoke(command); + + // then + assertThatThrownBy(executable).isInstanceOf(UsernameAlreadyExistException.class); + } + +}