Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
kiblykat committed Mar 24, 2024
2 parents ad07996 + 7fb533e commit 4175791
Show file tree
Hide file tree
Showing 16 changed files with 613 additions and 38 deletions.
105 changes: 105 additions & 0 deletions src/main/java/sg/com/smartinventory/utility/Utility.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package sg.com.smartinventory.utility;

public class Utility {
/**
* Get the method name of the caller.
* <p>
* Java 9 introduced the Stack-Walking API to traverse the JVM stack frames in a
* lazy and efficient manner.
* First, we get a StackWalker instance using the getInstance() factory method.
* Then we use the walk() method to traverse the stack frames from the top to
* the bottom:
* <p>
* <ul>
* <li>The walk() method can convert a stream of stack frames —
* Stream<StackFrame> — to anything.
* <li>The first element in the given stream is the top frame on the stack.
* <li>The top frame on the stack always represents the currently executing
* method.
* </ul>
* <p>
* Therefore, if we get the first element from the stream, we’ll know the
* currently executing method details. More specifically, we can use
* StackFrame.getMethodName() to find the method name.
* <p>
* Compared to other approaches (more on them later), the Stack-Walking API has
* a few advantages:
* <p>
* <ul>
* <ul>
* No need to create a dummy anonymous inner class instance — new
* Object().getClass() {}
* <ul>
* No need to create a dummy exception — new Throwable()
* <ul>
* No need to eagerly capture the whole stacktrace, which can be costly
* <p>
* <ul>
* On the contrary, the StackWalker only walks the stack one by one in a lazy
* fashion. In this case, it only fetches the top frame, as opposed to the
* stacktrace approach which captures all the frames eagerly.
*
* @param levelsUp The number of levels up the stack trace.
*
* @return The method name of the caller.
*/
public static String getMethodName(int levelsUp) {
// Check if the levelsUp is less than 0. If it is, throw an exception.
if (levelsUp < 0) {
throw new IllegalArgumentException("levelsUp must be greater than or equal to 0. ");
}

// Get the method name of the caller. The top is this function name itself, so
// it should be skipped.
return StackWalker.getInstance()
.walk(s -> s.skip(1 + levelsUp).findFirst())
.get()
.getMethodName();
}

/**
* Get the current method name.
*
* @return The current method name.
*
* @see #getMethodName()
*/
public static String getCurrentMethodName() {
// Get the method name of the caller. You need to skip 1 level up to get the
// current method name as you are calling a base function below it.
return getMethodName(1);
}

/**
* Get the caller method name.
*
* @return The caller method name.
*
* @see #getMethodName()
*/
public static String getCallerMethodName() {
// Get the method name of the caller. You need to skip 2 level up to get the
// current method name as you are calling a base function below it.
return getMethodName(2);
}

/**
* Get the caller method name.
*
* @param levelsUp The number of levels up the stack trace.
*
* @return The caller method name.
*
* @see #getCallerMethodName()
*/
public static String getCallerMethodName(int levelsUp) {
// Check if the levelsUp is less than 0. If it is, throw an exception.
if (levelsUp < 0) {
throw new IllegalArgumentException("levelsUp must be greater than or equal to 0. ");
}

// Get the method name of the caller. You need to skip 1 level up to get the
// current method name as you are calling a base function below it.
return getMethodName(2 + levelsUp);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
package sg.com.smartinventory;

import static sg.com.smartinventory.utility.Utility.*;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SmartInventoryApplicationTests {
/// Name this according to your class name.
// The Logback library defines 5 log levels in order of priority: TRACE, DEBUG,
// INFO, WARN, ERROR, with each of these having a corresponding logging method:
// trace(), debug(), info(), warn(), error().
private static final Logger test_logger = LoggerFactory.getLogger(SmartInventoryApplicationTests.class);

@Test
void contextLoads() {
test_logger.info("Starting test: " + getCurrentMethodName() + ". ");

test_logger.info("Ending test: " + getCurrentMethodName() + ". ");
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package sg.com.smartinventory.controllers;

import static sg.com.smartinventory.utility.Utility.*;

import static org.junit.jupiter.api.Assertions.*;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -35,10 +41,21 @@ public class CustomerControllerTest {
// trace(), debug(), info(), warn(), error().
private static final Logger test_logger = LoggerFactory.getLogger(CustomerControllerTest.class);

@DisplayName("Create customer")
// Test Setup and Teardown configuration.
@BeforeEach
void init() {

}

@AfterEach
void teardown() {

}

@DisplayName("Create Customer")
@Test
public void createCustomerTest() throws Exception {
test_logger.info("Starting test: createCustomerTest. ");
test_logger.info("Starting test: " + getCurrentMethodName() + ". ");

// Step 1: Create a Customer object
Customer newCustomer = Customer.builder().firstName("Jackie").lastName("Chan").country("Hong Kong")
Expand All @@ -60,6 +77,6 @@ public void createCustomerTest() throws Exception {
.andExpect(jsonPath("$.firstName").value("Jackie"))
.andExpect(jsonPath("$.lastName").value("Chan"));

test_logger.info("Ending test: createCustomerTest. ");
test_logger.info("Ending test: " + getCurrentMethodName() + ". ");
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package sg.com.smartinventory.controllers;

import static sg.com.smartinventory.utility.Utility.*;

import static org.junit.jupiter.api.Assertions.*;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -33,12 +39,23 @@ public class ProductControllerTest {
// The Logback library defines 5 log levels in order of priority: TRACE, DEBUG,
// INFO, WARN, ERROR, with each of these having a corresponding logging method:
// trace(), debug(), info(), warn(), error().
private static final Logger test_logger = LoggerFactory.getLogger(CustomerControllerTest.class);
private static final Logger test_logger = LoggerFactory.getLogger(ProductControllerTest.class);

// Test Setup and Teardown configuration.
@BeforeEach
void init() {

}

@AfterEach
void teardown() {

}

@DisplayName("Create product")
@DisplayName("Create Product")
@Test
public void createProductTest() throws Exception {
test_logger.info("Starting test: createProductTest. ");
test_logger.info("Starting test: " + getCurrentMethodName() + ". ");

// Step 1: Create a Product object
Product newProduct = Product.builder().category("Electronics").name("Smartphone")
Expand All @@ -60,6 +77,6 @@ public void createProductTest() throws Exception {
.andExpect(jsonPath("$.category").value("Electronics"))
.andExpect(jsonPath("$.name").value("Smartphone"));

test_logger.info("Ending test: createProductTest. ");
test_logger.info("Ending test: " + getCurrentMethodName() + ". ");
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package sg.com.smartinventory.controllers;

import static sg.com.smartinventory.utility.Utility.*;

import static org.junit.jupiter.api.Assertions.*;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

Expand All @@ -13,7 +19,6 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

Expand All @@ -30,39 +35,32 @@ public class ReviewControllerTest {
@Autowired
private ObjectMapper objectMapper;

/**
* Convert JSON Result to object.
*
* @param result The contents.
* @param tClass The expected object class.
* @return The result as a class object.
* @throws Exception
*/
public <T> T fromJsonResult(MvcResult result, Class<T> tClass) throws Exception {
return this.objectMapper.readValue(result.getResponse().getContentAsString(), tClass);
/// Name this according to your class name.
// The Logback library defines 5 log levels in order of priority: TRACE, DEBUG,
// INFO, WARN, ERROR, with each of these having a corresponding logging method:
// trace(), debug(), info(), warn(), error().
private static final Logger test_logger = LoggerFactory.getLogger(ReviewControllerTest.class);

// Test Setup and Teardown configuration.
@BeforeEach
void init() {

}

@AfterEach
void teardown() {

}

/**
* Convert object to JSON bytes.
* Test the creation of a Review.
*
* @param object The object to JSON-ify.
* @return Byte array with JSON representation.
* @throws Exception
*/
public byte[] toJson(Object object) throws Exception {
return this.objectMapper.writeValueAsString(object).getBytes();
}

/// Name this according to your class name.
// The Logback library defines 5 log levels in order of priority: TRACE, DEBUG,
// INFO, WARN, ERROR, with each of these having a corresponding logging method:
// trace(), debug(), info(), warn(), error().
private static final Logger test_logger = LoggerFactory.getLogger(CustomerControllerTest.class);

@DisplayName("Create review")
@DisplayName("Create Review")
@Test
public void createReviewTest() throws Exception {
test_logger.info("Starting test: createReviewTest. ");
test_logger.info("Starting test: " + getCurrentMethodName() + ". ");

// Step 1: Create a Review object
Review newReview = Review.builder().category("Electronics")
Expand Down Expand Up @@ -93,6 +91,6 @@ public void createReviewTest() throws Exception {
// Review ReviewObject = fromJsonResult(Result, Review.class);

// test_logger.error("Ending test: createReviewTest. ");
test_logger.info("Ending test: createReviewTest. ");
test_logger.info("Ending test: " + getCurrentMethodName() + ". ");
}
}
}
28 changes: 28 additions & 0 deletions src/test/java/sg/com/smartinventory/entities/CustomerTest.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package sg.com.smartinventory.entities;

import static sg.com.smartinventory.utility.Utility.*;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import org.mockito.InjectMocks;
import org.mockito.Mock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sg.com.smartinventory.repositories.CustomerRepository;
import sg.com.smartinventory.serviceImpls.CustomerServiceImpl;

Expand All @@ -16,9 +25,28 @@ public class CustomerTest {
@InjectMocks
CustomerServiceImpl customerService;

/// Name this according to your class name.
// The Logback library defines 5 log levels in order of priority: TRACE, DEBUG,
// INFO, WARN, ERROR, with each of these having a corresponding logging method:
// trace(), debug(), info(), warn(), error().
private static final Logger test_logger = LoggerFactory.getLogger(CustomerTest.class);

// Test Setup and Teardown configuration.
@BeforeEach
void init() {

}

@AfterEach
void teardown() {

}

@DisplayName("Customer Test")
@Test
public void customerTest() throws Exception {
test_logger.info("Starting test: " + getCurrentMethodName() + ". ");

test_logger.info("Ending test: " + getCurrentMethodName() + ". ");
}
}
Loading

0 comments on commit 4175791

Please sign in to comment.