From 147b57d6821d2bff18f2634fdc374b7a3b485e61 Mon Sep 17 00:00:00 2001 From: deseraekaufman Date: Fri, 1 Apr 2022 15:56:09 -0400 Subject: [PATCH 1/2] jr. dev notes and attempt at writing tests --- pom.xml | 6 ++++ .../java/com/bravo/user/config/AppConfig.java | 8 +++++ .../com/bravo/user/config/SwaggerConfig.java | 5 ++- .../user/controller/AddressController.java | 9 +++-- .../user/controller/LoginController.java | 5 ++- .../bravo/user/model/dto/ReflectClassDto.java | 4 +-- .../java/com/bravo/user/utility/DateUtil.java | 2 ++ .../java/com/bravo/user/utility/PageUtil.java | 8 +++-- .../com/bravo/user/utility/ReflectUtil.java | 27 ++++++++++++--- .../com/bravo/user/utility/ValidatorUtil.java | 7 ++-- .../user/service/AddressServiceTest.java | 27 +++++++++++---- .../com/bravo/user/utility/DateUtilTest.java | 33 +++++++++++++++++++ .../com/bravo/user/utility/PageUtilTest.java | 29 ++++++++++++++++ .../bravo/user/utility/ReflectUtilTest.java | 7 ++++ .../bravo/user/utility/ValidatorUtilTest.java | 21 ++++++++++++ 15 files changed, 176 insertions(+), 22 deletions(-) create mode 100644 src/test/java/com/bravo/user/utility/DateUtilTest.java create mode 100644 src/test/java/com/bravo/user/utility/PageUtilTest.java create mode 100644 src/test/java/com/bravo/user/utility/ReflectUtilTest.java create mode 100644 src/test/java/com/bravo/user/utility/ValidatorUtilTest.java diff --git a/pom.xml b/pom.xml index 5b31f78..109ab59 100644 --- a/pom.xml +++ b/pom.xml @@ -114,6 +114,12 @@ springfox-swagger-ui 2.5.0 + + junit + junit-dep + 4.13 + test + diff --git a/src/main/java/com/bravo/user/config/AppConfig.java b/src/main/java/com/bravo/user/config/AppConfig.java index 902eb8f..591e691 100644 --- a/src/main/java/com/bravo/user/config/AppConfig.java +++ b/src/main/java/com/bravo/user/config/AppConfig.java @@ -18,6 +18,14 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +/* +Serializers-Deserializers take a object and convert it to a string of JSON format and vice versa + +Never worked with Jackson before but looks like it is a Java library that is used to create serializers/deserializers + +*/ + +//tags the class as a source of bean definitions for the application context in spring @Configuration public class AppConfig { diff --git a/src/main/java/com/bravo/user/config/SwaggerConfig.java b/src/main/java/com/bravo/user/config/SwaggerConfig.java index f0d9598..4986f01 100644 --- a/src/main/java/com/bravo/user/config/SwaggerConfig.java +++ b/src/main/java/com/bravo/user/config/SwaggerConfig.java @@ -15,7 +15,10 @@ @Configuration @EnableSwagger2 public class SwaggerConfig { - +/* +Docket class - Docket is a builder which is intended to be the primary interface into the swagger-springmvc framework. +It provides sensible defaults and convenience methods for configuration. + */ @Bean public Docket docket(){ return new Docket(DocumentationType.SWAGGER_2) diff --git a/src/main/java/com/bravo/user/controller/AddressController.java b/src/main/java/com/bravo/user/controller/AddressController.java index 10ee70e..323c208 100644 --- a/src/main/java/com/bravo/user/controller/AddressController.java +++ b/src/main/java/com/bravo/user/controller/AddressController.java @@ -11,19 +11,22 @@ import com.bravo.user.model.dto.AddressDto; import com.bravo.user.service.AddressService; import com.bravo.user.validator.UserValidator; - +//I understand the controllers and that they handle HTTP requests +//this controller specifically is handling requests related to Addresses @RequestMapping(value = "/address") @SwaggerController public class AddressController { private final AddressService addressService; private final UserValidator userValidator; - + //constructor for AddressController class public AddressController(AddressService addressService, UserValidator userValidator) { this.addressService = addressService; this.userValidator = userValidator; } - + //here we will pass a user id to the endpoint and recieve a response + //@PathVariable annotation marks the userId as the required argument + //I have only seen @RequestMapping(method="GET") but as I understand, @GetMapping does the same thing @GetMapping(value = "/retrieve/{userId}") @ResponseBody public List retrieve(final @PathVariable String userId) { diff --git a/src/main/java/com/bravo/user/controller/LoginController.java b/src/main/java/com/bravo/user/controller/LoginController.java index e2f2957..b42f628 100644 --- a/src/main/java/com/bravo/user/controller/LoginController.java +++ b/src/main/java/com/bravo/user/controller/LoginController.java @@ -9,6 +9,9 @@ import org.springframework.web.bind.annotation.RequestMapping; @RequestMapping(value = "/login") +//also the first time I have seen/used Swagger but it looks like its a tool to help you +//build consumer and document RESTful APIs +//I have worked with Postman only in the past but they seem similar? @SwaggerController public class LoginController { @@ -17,7 +20,7 @@ public class LoginController { public LoginController(LoginService loginService) { this.loginService = loginService; } - + //a post request means we will be adding information to our database @PostMapping public void login(final @RequestBody LoginDto request, HttpServletResponse httpResponse){ if(request.getUsername() == null){ diff --git a/src/main/java/com/bravo/user/model/dto/ReflectClassDto.java b/src/main/java/com/bravo/user/model/dto/ReflectClassDto.java index 2b5790f..bcac3d8 100644 --- a/src/main/java/com/bravo/user/model/dto/ReflectClassDto.java +++ b/src/main/java/com/bravo/user/model/dto/ReflectClassDto.java @@ -7,10 +7,10 @@ import java.util.Set; import java.util.stream.Collectors; import lombok.Data; - +//Data Transfer Object class for reflect @Data public class ReflectClassDto { - + //private instance variables can only be accessed by methods within this class private final Class type; private List> fields; diff --git a/src/main/java/com/bravo/user/utility/DateUtil.java b/src/main/java/com/bravo/user/utility/DateUtil.java index dd447b2..28ccba9 100644 --- a/src/main/java/com/bravo/user/utility/DateUtil.java +++ b/src/main/java/com/bravo/user/utility/DateUtil.java @@ -6,6 +6,8 @@ @UtilityClass public class DateUtil { + //static final means that this is a compile-time constant - no instance allowed outside of class + //DateTimeFormatter - parses date into string of the pattern specified date/time pattern public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); public static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss"); diff --git a/src/main/java/com/bravo/user/utility/PageUtil.java b/src/main/java/com/bravo/user/utility/PageUtil.java index 15d7f85..0b0b60e 100644 --- a/src/main/java/com/bravo/user/utility/PageUtil.java +++ b/src/main/java/com/bravo/user/utility/PageUtil.java @@ -1,29 +1,33 @@ package com.bravo.user.utility; import javax.servlet.http.HttpServletResponse; +//learned that lombok is a Java library tool that generates code for minimizing boilerplate code import lombok.experimental.UtilityClass; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @UtilityClass public class PageUtil { - + //setting default page size to 20 private static final int DEFAULT_SIZE = 20; + //to create a new page, we need 2 arguments - an integer for the page number and an integer for the size public static PageRequest createPageRequest(final Integer page, final Integer size){ return createPageRequest(page, size, DEFAULT_SIZE); } - + // public static PageRequest createPageRequest( final Integer page, final Integer size, final Integer defaultSize ){ + //I don't quite understand what is going on here, final int pg = page != null && page > 0 ? page - 1 : 0; final int sz = size != null && size > 0 ? size : defaultSize; return PageRequest.of(pg, sz); } + //updating page headers with public static void updatePageHeaders( final HttpServletResponse httpResponse, final Page page, diff --git a/src/main/java/com/bravo/user/utility/ReflectUtil.java b/src/main/java/com/bravo/user/utility/ReflectUtil.java index 859642d..a262f79 100644 --- a/src/main/java/com/bravo/user/utility/ReflectUtil.java +++ b/src/main/java/com/bravo/user/utility/ReflectUtil.java @@ -13,23 +13,35 @@ @UtilityClass public class ReflectUtil { - + //logging components help developers debug, have logger, handler/appender, layouts/formatters + //when a logger is called, logging component records the event in log handler and forwards to appropriate appender private static final Logger LOGGER = LoggerFactory.getLogger(ReflectUtil.class); + //describe method takes in an instance of an object as a parameter and returns a ReflectClassDto object public static ReflectClassDto describe(final Object instance){ - final Class instanceClass = instance.getClass(); + //a java bean is just a standard that specifies - all properties are private, a public no-argument constructor, implements the Serializable interface + //what is the Serializable interface? Serializable objects can be written to streams, and hence files, object databases, etc. BeanInfo beanInfo; + //try catch loop prevents compile errors in this case IntrospectionException try { + //Introspector! this is new for me too. This class provides a standard way for tools to learn about the + //the properties, events and methods supposed by a target java bean beanInfo = Introspector.getBeanInfo(instanceClass); - + //try/catch and introspection exception here, and call the logger to log the error } catch (IntrospectionException e) { LOGGER.error("ERROR", e); return null; } + //here we will create the new instance of the reflectDTO class that we will return when the method is called + //Reflection is a fuzzy concept but would love to learn more about it + // final ReflectClassDto reflection = new ReflectClassDto(instanceClass); + //for each loop for(PropertyDescriptor desc : beanInfo.getPropertyDescriptors()){ + //I think this is saying basically if the class equals the name of descriptor we will use a get method on the "Name" property (?) if("class".equals(desc.getName())){ + //if condition is true, we continue on in loop continue; } final ReflectFieldDto field = new ReflectFieldDto<>(desc.getPropertyType()); @@ -37,9 +49,10 @@ public static ReflectClassDto describe(final Object instance){ field.setValue(invokeReadMethod(desc, instance)); reflection.getFields().add(field); } + //we return the reflection we created above return reflection; } - +// private Object invokeReadMethod(final PropertyDescriptor descriptor, final Object instance){ try { @@ -51,3 +64,9 @@ private Object invokeReadMethod(final PropertyDescriptor descriptor, final Objec } } } + +/* + + + + */ \ No newline at end of file diff --git a/src/main/java/com/bravo/user/utility/ValidatorUtil.java b/src/main/java/com/bravo/user/utility/ValidatorUtil.java index f2e25bb..6c6b321 100644 --- a/src/main/java/com/bravo/user/utility/ValidatorUtil.java +++ b/src/main/java/com/bravo/user/utility/ValidatorUtil.java @@ -10,8 +10,11 @@ @UtilityClass public class ValidatorUtil { + // means type generic, ... means that we might be getting multiple parameters + //this method is checking whether passed in value is empty public static boolean isEmpty(T value, String... excludeFields){ - + //I learned that a reflection class allows us to inspect and modify an object's behavior at runtime + //instantiating a variable of the reflection class data transfer object final ReflectClassDto reflection = ReflectUtil.describe(value); if(reflection == null){ throw new IllegalStateException(String.format("could not describe class: '%s'", value)); @@ -24,7 +27,7 @@ public static boolean isEmpty(T value, String... excludeFields){ } return true; } - +//validation methods public static boolean isInvalid(T value){ return !isValid(value); } diff --git a/src/test/java/com/bravo/user/service/AddressServiceTest.java b/src/test/java/com/bravo/user/service/AddressServiceTest.java index 9be89a1..507f766 100644 --- a/src/test/java/com/bravo/user/service/AddressServiceTest.java +++ b/src/test/java/com/bravo/user/service/AddressServiceTest.java @@ -28,33 +28,46 @@ @ExtendWith(SpringExtension.class) @SpringBootTest class AddressServiceTest { - + //I looked at tests that have already been written to try to get a better understanding + //of the different components of this app + //autowired ? - allows you to inject the object dependency implicitly @Autowired private AddressService addressService; - + //mock bean? this will replace any existing bean of the same type in the application context + //according to what I have read, you can also use a @Qualifier notation and pass in qualifier metadata + //mock resource mapper to use in tests @MockBean private ResourceMapper resourceMapper; + //mock address repo to use in tests @MockBean private AddressRepository addressRepository; - + //empty (?) list of data transfer object - addresses private List dtoAddresses; @BeforeEach public void beforeEach() { - final List ids = IntStream.range(1, 10).boxed().collect(Collectors.toList()); + /* wow! this is my first time learning about the Collectors class - pretty cool! + -allows us to accumulate/reduce values into a collection + IntStream.range()? - sequence of primitive int values that fall between given range, .boxed() - each element boxed to an Integer + */ + final List ids = IntStream.range(1, 10).boxed().collect(Collectors.toList()); + //here we use stream() to save a list of addresses final List
daoAddresses = ids.stream() .map(id -> createAddress(Integer.toString(id))).collect(Collectors.toList()); - + //I think what is happening now is the id's are being mapped to the daoAddresses list + //when keyword - Mockito class! also new to me - sent down a new rabbit hole + //Mockito is a mocking framework for unit tests in Java - allows the creation of test double objects in automated unit tests + //"used to mock interfaces so that a dummy functionality can be added to a mock interface that can be used in testing" when(addressRepository.findByUserId(anyString())).thenReturn(daoAddresses); - + //this keyword refers to this specific instance this.dtoAddresses = ids.stream().map(id -> createAddressDto(Integer.toString(id))) .collect(Collectors.toList()); when(resourceMapper.convertAddresses(daoAddresses)).thenReturn(dtoAddresses); } - +//testing that endpoint retrieves correct id value @Test void retrieveByUserId() { final String userId = "123a-456b"; diff --git a/src/test/java/com/bravo/user/utility/DateUtilTest.java b/src/test/java/com/bravo/user/utility/DateUtilTest.java new file mode 100644 index 0000000..00aa825 --- /dev/null +++ b/src/test/java/com/bravo/user/utility/DateUtilTest.java @@ -0,0 +1,33 @@ +package com.bravo.user.utility; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.util.Assert; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Date; + +public class DateUtilTest { + //expected objects + + public void test_date_time_formatter_date_only_format() { + + String expectedOutcome = "2022-04-01"; + Date testDate = new Date(4-1-22); + DateTimeFormatter expectedFormatterDate = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + //i'm not entirely sure how to proceed with this but my thought process is to write a test + //that makes sure the output of DateTimeFormatter is the pattern specified + //Assertions.assertEquals(expectedOutcome, expectedFormatterDate.format(testDate)); + + } + + + + DateTimeFormatter expectedFormatterDateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + DateTimeFormatter expectedFormatterTime = DateTimeFormatter.ofPattern("HH:mm:ss"); + + + +} diff --git a/src/test/java/com/bravo/user/utility/PageUtilTest.java b/src/test/java/com/bravo/user/utility/PageUtilTest.java new file mode 100644 index 0000000..87d1587 --- /dev/null +++ b/src/test/java/com/bravo/user/utility/PageUtilTest.java @@ -0,0 +1,29 @@ +package com.bravo.user.utility; + + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; + +@SpringBootTest +public class PageUtilTest { + //I have never used @Mock before + private PageUtil pageUtil; + //before annotation indicates that this method runs prior to every test + @BeforeEach + private void beforeEach(){ + this.pageUtil = null; + } + //annotation indicates that the method is a test method - test methods are always public, always return void, and take no arguments + @Test + public void test_create_page_request_should_return_new_page_request(){ + //my thought process here is, I need to test createPageRequest method on a page util object + //and then check that the new PageRequest is returned + PageRequest testPage = pageUtil.createPageRequest(1,3); + //I am not quite sure how to return the expected result + Assertions.assertEquals(testPage,testPage); + } + +} diff --git a/src/test/java/com/bravo/user/utility/ReflectUtilTest.java b/src/test/java/com/bravo/user/utility/ReflectUtilTest.java new file mode 100644 index 0000000..be46b3b --- /dev/null +++ b/src/test/java/com/bravo/user/utility/ReflectUtilTest.java @@ -0,0 +1,7 @@ +package com.bravo.user.utility; + +public class ReflectUtilTest { + + //I would write a unit test for: + +} diff --git a/src/test/java/com/bravo/user/utility/ValidatorUtilTest.java b/src/test/java/com/bravo/user/utility/ValidatorUtilTest.java new file mode 100644 index 0000000..e8ac40c --- /dev/null +++ b/src/test/java/com/bravo/user/utility/ValidatorUtilTest.java @@ -0,0 +1,21 @@ +package com.bravo.user.utility; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class ValidatorUtilTest { + //creating test object + private ValidatorUtil validatorUtil; + //reset our test object before each test + @BeforeEach + public void beforeEach(){ + this.validatorUtil = null; + } + + @Test + public void isEmpty(){ + boolean testValue = ValidatorUtil.isEmpty("cat"); + + } + +} From 1ca0c9a090e8c8fda1c50b96760f90387960c3db Mon Sep 17 00:00:00 2001 From: deseraekaufman Date: Fri, 1 Apr 2022 16:02:16 -0400 Subject: [PATCH 2/2] small cleanups in notes --- src/main/java/com/bravo/user/utility/PageUtil.java | 1 - src/main/java/com/bravo/user/utility/ReflectUtil.java | 9 +-------- src/test/java/com/bravo/user/utility/PageUtilTest.java | 2 +- .../java/com/bravo/user/utility/ReflectUtilTest.java | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/bravo/user/utility/PageUtil.java b/src/main/java/com/bravo/user/utility/PageUtil.java index 0b0b60e..58e6ff8 100644 --- a/src/main/java/com/bravo/user/utility/PageUtil.java +++ b/src/main/java/com/bravo/user/utility/PageUtil.java @@ -15,7 +15,6 @@ public class PageUtil { public static PageRequest createPageRequest(final Integer page, final Integer size){ return createPageRequest(page, size, DEFAULT_SIZE); } - // public static PageRequest createPageRequest( final Integer page, final Integer size, diff --git a/src/main/java/com/bravo/user/utility/ReflectUtil.java b/src/main/java/com/bravo/user/utility/ReflectUtil.java index a262f79..f855634 100644 --- a/src/main/java/com/bravo/user/utility/ReflectUtil.java +++ b/src/main/java/com/bravo/user/utility/ReflectUtil.java @@ -35,7 +35,6 @@ public static ReflectClassDto describe(final Object instance){ } //here we will create the new instance of the reflectDTO class that we will return when the method is called //Reflection is a fuzzy concept but would love to learn more about it - // final ReflectClassDto reflection = new ReflectClassDto(instanceClass); //for each loop for(PropertyDescriptor desc : beanInfo.getPropertyDescriptors()){ @@ -52,7 +51,7 @@ public static ReflectClassDto describe(final Object instance){ //we return the reflection we created above return reflection; } -// + private Object invokeReadMethod(final PropertyDescriptor descriptor, final Object instance){ try { @@ -64,9 +63,3 @@ private Object invokeReadMethod(final PropertyDescriptor descriptor, final Objec } } } - -/* - - - - */ \ No newline at end of file diff --git a/src/test/java/com/bravo/user/utility/PageUtilTest.java b/src/test/java/com/bravo/user/utility/PageUtilTest.java index 87d1587..6eaf719 100644 --- a/src/test/java/com/bravo/user/utility/PageUtilTest.java +++ b/src/test/java/com/bravo/user/utility/PageUtilTest.java @@ -9,7 +9,7 @@ @SpringBootTest public class PageUtilTest { - //I have never used @Mock before + private PageUtil pageUtil; //before annotation indicates that this method runs prior to every test @BeforeEach diff --git a/src/test/java/com/bravo/user/utility/ReflectUtilTest.java b/src/test/java/com/bravo/user/utility/ReflectUtilTest.java index be46b3b..0fb2e8f 100644 --- a/src/test/java/com/bravo/user/utility/ReflectUtilTest.java +++ b/src/test/java/com/bravo/user/utility/ReflectUtilTest.java @@ -2,6 +2,6 @@ public class ReflectUtilTest { - //I would write a unit test for: + //Need to write tests for: describe(), invokeReadMethod() }