- Lab
- Core Tech

Guided: Secure and Test an Auction Application with Spring Framework 6
In this compact yet comprehensive Code Lab, we'll journey into the realms of application security and testing with the cutting-edge Spring Framework 6. Our hands-on project will revolve around an auction application, which we'll secure and test. You'll gain practical proficiency in integrating Spring Security for managing authentication and authorization, You'll gain tangible experience in testing Spring 6 applications using tools like JUnit and Hamcrest, equipping you to write and execute a range of tests from unit and integration to end-to-end to ensure optimal functionality.

Path Info
Table of Contents
-
Challenge
Item Class Testing
In this module, you will be learning how to write a simple JUnit test for the
Item
class. JUnit is a popular testing framework for Java, and it's an essential tool for any Java developer. The goal of this module is to help you understand how to create tests that validate the behavior of your code.Relevant File: src/test/java/com/pluralsight/auction/ItemTest.java
Task 1: Define Test Variables
Let's start with defining some data that we'll use for testing. In the
testItem
method, create the following variables:itemName
: a String representing the name of the item. Set it to "testItem".itemDescription
: a String representing the item's description. Set it to "testDescription".itemSeller
: a String representing the seller's name. Set it to "testSeller".itemPrice
: a double representing the item's price. Set it to 100.0.itemReserve
: a double representing the item's reserve price. Set it to 50.0.
The purpose of these variables is to act as "test data". We will use them to create an instance of
Item
and check if the item's properties match these values.Task 2: Instantiate the Item
Now that you have your test data, let's create an instance of
Item
. In thetestItem
method, instantiate anItem
with the variables you defined in Task 1.Remember, the constructor of the
Item
class should look something like this:Item(String name, String description, String seller, double price, double reserve)
.
Use the variables you defined earlier as arguments when creating the
Item
.This
Item
instance will be the "system under test". It's the object that we're going to test in this module.Task 3: Assert the Item's Properties
The final part is to validate that the
Item
's properties match the values we passed to it. We do this with assertions.In the
testItem
method, write fiveassertEquals
statements to verify that:- The item's name matches
itemName
. - The item's description matches
itemDescription
. - The item's seller matches
itemSeller
. - The item's price matches
itemPrice
. - The item's reserve matches
itemReserve
.
Remember,
assertEquals
takes two arguments: the expected value and the actual value. The expected value should be the test data, and the actual value should be the corresponding property of theItem
.Important Note: Make sure to not mix up the order of the arguments in
assertEquals
. The first argument is the expected value (your test data), and the second argument is the actual value (theItem
property). Mixing up these arguments won't cause your test to fail, but it can make the error messages confusing if a test does fail.After you complete these tasks, you should have a working JUnit test for the
Item
class. This test validates that theItem
's properties are correctly set during instantiation.To run the tests type the comand
gradle test
in the terminal The solution can be found in thesolution
folder. -
Challenge
Item Repository Testing
In this module, you'll delve into data persistence testing using Spring's
DataJpaTest
annotation. You'll be testing theItemRepository
, which is an interface for generic CRUD operations on ourItem
entity.Relevant File: src/test/java/com/pluralsight/auction/ItemRepositoryTest.java
Task 1: Create a Test Item
First, you need to create an instance of
Item
that will be used for testing. Within thetestSaveAndFind
method, instantiate anItem
with the following parameters:- Name: "testItem"
- Description: "testDescription"
- Seller: "testSeller"
- Price: 100.0
- Reserve: 50.0
This
Item
instance will be the "system under test". It's the object that we're going to persist and retrieve from the database.Task 2: Save the Test Item
Now, let's persist the
Item
instance you created in the previous task. Use thesave
method of theItemRepository
to save theItem
instance to the database.Remember to assign the result of the
save
method back to theitem
variable. This is because thesave
method returns a new instance that represents the persisted state (including the generated ID).Task 3: Retrieve the Test Item
After persisting the
Item
instance, you'll want to retrieve it to ensure it was saved correctly.Use the
findById
method of theItemRepository
to retrieve theItem
from the database. The argument should be the ID of theitem
you just saved.Remember,
findById
returns anOptional<Item>
, so you'll need to handle the possibility that the item might not be found.Task 4: Assert the Retrieved Item
The final part of this task is to validate that the item retrieved from the database matches the item you saved.
First, assert that the
Optional<Item>
is not empty using theassertTrue
method and theisPresent
method ofOptional
. This ensures that an item was actually returned from the database.Next, assert that the name of the retrieved item matches the name of the item you saved. Use the
get
method ofOptional
to retrieve theItem
and thegetName
method ofItem
to get its name. Then, useassertEquals
to compare it to the name of the item you saved.Important Note: Be cautious when using the
get
method ofOptional
. It throws aNoSuchElementException
if theOptional
is empty. In this case, it's safe to use because you've already checked that theOptional
is not empty.After completing these tasks, you should have a working test that validates the basic functionality of the
ItemRepository
. This test ensures that anItem
can be successfully saved and retrieved from the database.To run the tests type the comand
gradle test
in the terminal The solution can be found in thesolution
folder. -
Challenge
Item Controller Testing
In this module, you'll be testing the
ItemController
class, which is responsible for handling HTTP requests related toItem
instances. TheMockMvc
class will be used to perform HTTP requests, and theItemRepository
will be mocked using Mockito.Relevant File: src/test/java/com/pluralsight/auction/ItemControllerTest.java
Task 1: Create a Test Item and Configure Mock Behavior
First, create a test
Item
instance within thetestListItems
method, similar to what you've done in previous modules.Next, define a
List<Item>
containing the test item. This list will represent the items in the repository.Then, configure the mock
ItemRepository
to return this list when itsfindAll
method is called. Mockito'swhen
method lets you define what should be returned when a certain method is called on a mock object.Task 2: Perform Request and Assert Model
Now, use
MockMvc
to perform a GET request to the root URL ("/").Use the
andExpect
method to validate the response. You should check the following:- The HTTP status is OK.
- The view name is "index".
- The model contains an attribute named "items".
- The "items" attribute equals the list of items you defined earlier.
The
status
,view
, andmodel
methods are static imports fromMockMvcResultMatchers
. They returnResultMatcher
instances that can be used to verify different aspects of the HTTP response.Task 3: Perform Request and Assert View
Create another test method,
testListItemsView
, to validate the content of the view.Set up the test item, the list of items, and the mock behavior exactly like in the previous task.
Use
MockMvc
to perform a GET request to the root URL ("/") again.This time, check the following in addition to the HTTP status and view name:
- The response content contains the string "Auction Items".
- The response content contains the name, description, seller, and price of the test item.
The
content
method is another static import fromMockMvcResultMatchers
. It returnsResultMatcher
instances that verify the content of the HTTP response.After completing these tasks, you should have two working tests for the
ItemController
.testListItems
checks that the model contains the correct items, whiletestListItemsView
ensures that these items are correctly displayed in the view.To run the tests type the comand
gradle test
in the terminal The solution can be found in thesolution
folder. -
Challenge
Spring Security Configuration
In this module, you'll be setting up Spring Security to secure your application. You'll configure HTTP security, password encoding, and user details service.
Relevant File: src/main/java/com/pluralsight/auction/SecurityConfig.java
Task 1: HTTP Security Configuration
First, define a
SecurityFilterChain
bean to set up HTTP security. In thefilterChain
method, build aHttpSecurity
instance that defines which requests should be authorized and how users should authenticate themselves.Disable CSRF protection for simplicity, as it's not the focus of this module.
Permit all requests to static resources and the root URL ("/"). Requests to the "/admin" URL will require the user to have the "ADMIN" role.
Configure form-based login and logout. The login page URL, login processing URL, and default success URL will be "/login", "/login", and "/admin", respectively. You'll also permit all requests to these URLs.
The logout request matcher will be a new
AntPathRequestMatcher
for the "/logout" URL. All requests to this URL will also be permitted.Finally, build the
HttpSecurity
instance and return it.Task 2: Password Encoder Configuration
Next, define a
PasswordEncoder
bean. ThepasswordEncoder
method will return a newBCryptPasswordEncoder
instance.The
BCryptPasswordEncoder
uses the BCrypt hashing algorithm to encode passwords. It's a good choice for password encoding because it's computationally expensive, which makes it difficult for attackers to crack the hashed passwords.Task 3: User Details Service Configuration
The last task is to define a
UserDetailsService
bean. This service is responsible for loading user-specific data during authentication.In the
userDetailsService
method, you'll create anUserDetails
instance for an admin user. The username and password will both be "admin", and the user will have the "ADMIN" role. The password will be encoded using thePasswordEncoder
you defined earlier.Finally, return a new
InMemoryUserDetailsManager
with the admin user. TheInMemoryUserDetailsManager
is a simpleUserDetailsService
implementation that stores user details in memory.After completing these tasks, your application will be secured with Spring Security. Users will need to log in to access the "/admin" URL, and their passwords will be securely encoded.
To run view the application in the browser run the comand
gradle bootrun
in the terminal. Open the Simple Browser in VS Code by opening the command palette and typingSimple Browser
The solution can be found in thesolution
folder. -
Challenge
Admin Controller Testing
In this module, you'll be testing the
AdminController
class, which is responsible for handling HTTP requests related to admin operations. TheMockMvc
class will be used to perform HTTP requests, and theItemRepository
will be mocked using Mockito. The@WithMockUser
annotation will be used to simulate a logged-in user.Relevant File: src/test/java/com/pluralsight/auction/AdminControllerTest.java
Task 1: Set Up Test Environment
First, annotate the
AdminControllerTest
class with@SpringBootTest
and@AutoConfigureMockMvc
to set up a Spring Boot test environment with aMockMvc
instance.Then, define fields for
MockMvc
andItemRepository
and annotate them with@Autowired
and@MockBean
, respectively.@Autowired
will inject theMockMvc
instance, and@MockBean
will create a mockItemRepository
instance.Task 2: Create a Test Item and Configure Mock Behavior
Next, create a test method,
testListItems
, to validate the model and view.In the test method, you'll create a test
Item
instance and aList<Item>
containing the test item. This list will represent the items in the repository.Then, configure the mock
ItemRepository
to return this list when itsfindAll
method is called. Mockito'swhen
method lets you define what should be returned when a certain method is called on a mock object.Task 3: Simulate a Logged-In User
Annotate the test method with
@WithMockUser
to simulate a logged-in user. The username, password, and role will be "admin", "admin", and "ADMIN", respectively. This means the test will be run as if an admin user is logged in.Task 4: Perform Request and Assert Model
Now, use
MockMvc
to perform a GET request to the "/admin" URL.Use the
andExpect
method to validate the response. You should check the following:- The HTTP status is OK.
- The view name is "admin".
- The model contains an attribute named "items".
- The "items" attribute equals the list of items you defined earlier.
The
status
,view
, andmodel
methods are static imports fromMockMvcResultMatchers
. They returnResultMatcher
instances that can be used to verify different aspects of the HTTP response.After completing these tasks, you should have a working test for the
AdminController
. ThetestListItems
method checks that the model contains the correct items when an admin user is logged in.To run the tests type the comand
gradle test
in the terminal The solution can be found in thesolution
folder.
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.