diff --git a/src/main/java/com/bravo/user/controller/AddressController.java b/src/main/java/com/bravo/user/controller/AddressController.java new file mode 100644 index 0000000..82462e9 --- /dev/null +++ b/src/main/java/com/bravo/user/controller/AddressController.java @@ -0,0 +1,25 @@ +package com.bravo.user.controller; + +import com.bravo.user.annotation.SwaggerController; +import com.bravo.user.model.dto.AddressDto; +import com.bravo.user.service.AddressService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; + +@RequiredArgsConstructor +@RequestMapping(value = "/user") +@SwaggerController +public class AddressController { + private final AddressService addressService; + + @ResponseBody + @GetMapping(value = "/{userId}/address") + List findAll(@PathVariable String userId) { + return addressService.findAllByUserId(userId); + } +} diff --git a/src/main/java/com/bravo/user/dao/repository/AddressRepository.java b/src/main/java/com/bravo/user/dao/repository/AddressRepository.java new file mode 100644 index 0000000..338a701 --- /dev/null +++ b/src/main/java/com/bravo/user/dao/repository/AddressRepository.java @@ -0,0 +1,10 @@ +package com.bravo.user.dao.repository; + +import com.bravo.user.dao.model.Address; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +@Repository +public interface AddressRepository extends JpaRepository, JpaSpecificationExecutor
{ +} diff --git a/src/main/java/com/bravo/user/dao/specification/AddressSpecification.java b/src/main/java/com/bravo/user/dao/specification/AddressSpecification.java new file mode 100644 index 0000000..8c999ff --- /dev/null +++ b/src/main/java/com/bravo/user/dao/specification/AddressSpecification.java @@ -0,0 +1,19 @@ +package com.bravo.user.dao.specification; + +import com.bravo.user.dao.model.Address; +import com.bravo.user.model.filter.AddressFilter; +import lombok.RequiredArgsConstructor; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +@RequiredArgsConstructor +public class AddressSpecification extends AbstractSpecification
{ + private final AddressFilter filter; + + @Override + void doFilter(Root
root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + applyStringFilter(root.get("userId"), filter.getUserId()); + } +} diff --git a/src/main/java/com/bravo/user/model/filter/AddressFilter.java b/src/main/java/com/bravo/user/model/filter/AddressFilter.java new file mode 100644 index 0000000..81d7a46 --- /dev/null +++ b/src/main/java/com/bravo/user/model/filter/AddressFilter.java @@ -0,0 +1,12 @@ +package com.bravo.user.model.filter; + +import lombok.Builder; +import lombok.Data; + +import java.util.Set; + +@Data +@Builder +public class AddressFilter { + private Set userId; +} diff --git a/src/main/java/com/bravo/user/service/AddressService.java b/src/main/java/com/bravo/user/service/AddressService.java new file mode 100644 index 0000000..9bb4293 --- /dev/null +++ b/src/main/java/com/bravo/user/service/AddressService.java @@ -0,0 +1,29 @@ +package com.bravo.user.service; + +import com.bravo.user.dao.model.Address; +import com.bravo.user.dao.model.mapper.ResourceMapper; +import com.bravo.user.dao.repository.AddressRepository; +import com.bravo.user.dao.specification.AddressSpecification; +import com.bravo.user.model.dto.AddressDto; +import com.bravo.user.model.filter.AddressFilter; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Set; + +@RequiredArgsConstructor +@Service +public class AddressService { + private final AddressRepository addressRepository; + private final ResourceMapper resourceMapper; + + public List findAllByUserId(String userId) { + AddressFilter filter = AddressFilter.builder() + .userId(Set.of(userId)) + .build(); + AddressSpecification specification = new AddressSpecification(filter); + List
addresses = addressRepository.findAll(specification); + return resourceMapper.convertAddresses(addresses); + } +} diff --git a/src/test/java/com/bravo/user/controller/AddressControllerTest.java b/src/test/java/com/bravo/user/controller/AddressControllerTest.java new file mode 100644 index 0000000..d21f0dd --- /dev/null +++ b/src/test/java/com/bravo/user/controller/AddressControllerTest.java @@ -0,0 +1,49 @@ +package com.bravo.user.controller; + +import com.bravo.user.model.dto.AddressDto; +import com.bravo.user.service.AddressService; +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.test.web.servlet.MockMvc; + +import java.util.List; + +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(controllers = AddressController.class) +class AddressControllerTest { + @Autowired + private MockMvc mockMvc; + @MockBean + AddressService service; + + @Test + void getShouldReturnAddressWithMatchingZip() throws Exception { + AddressDto address = new AddressDto(); + address.setZip("test zip"); + AddressDto address1 = new AddressDto(); + address1.setZip("test zip 1"); + when(service.findAllByUserId("testId")).thenReturn(List.of(address, address1)); + mockMvc.perform(get("/user/testId/address")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].zip").value("test zip")) + .andExpect(jsonPath("$[1].zip").value("test zip 1")); + } + + @Test + void emptyIdShouldNotFindAnything() throws Exception { + mockMvc.perform(get("/user/address")).andExpect(status().isNotFound()); + } + + @Test + void noDataShouldReturnEmptyList() throws Exception { + mockMvc.perform(get("/user/test id/address")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isEmpty()); + } +} \ No newline at end of file diff --git a/src/test/java/com/bravo/user/service/AddressServiceTest.java b/src/test/java/com/bravo/user/service/AddressServiceTest.java new file mode 100644 index 0000000..5cf0bd0 --- /dev/null +++ b/src/test/java/com/bravo/user/service/AddressServiceTest.java @@ -0,0 +1,47 @@ +package com.bravo.user.service; + +import com.bravo.user.dao.model.Address; +import com.bravo.user.dao.model.mapper.ResourceMapper; +import com.bravo.user.dao.repository.AddressRepository; +import com.bravo.user.model.dto.AddressDto; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.jpa.domain.Specification; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@SpringBootTest +@ExtendWith(MockitoExtension.class) +class AddressServiceTest { + private AddressService testObj; + @Mock + private AddressRepository repository; + @Autowired + private ResourceMapper mapper; + + @BeforeEach + void setUp() { + testObj = new AddressService(repository, mapper); + } + + @Test + void findAllShouldCallRepositoryMethodAndMatchZip() { + Address address = new Address(); + String zip = "test zip"; + address.setZip(zip); + when(repository.findAll(any(Specification.class))).thenReturn(List.of(address)); + List results = testObj.findAllByUserId(""); + assertEquals(zip, results.get(0).getZip()); + verify(repository).findAll(any(Specification.class)); + } +} \ No newline at end of file