-



Download 8,6 Mb.
Pdf ko'rish
bet9/37
Sana18.01.2022
Hajmi8,6 Mb.
#383795
1   ...   5   6   7   8   9   10   11   12   ...   37
Bog'liq
Designing Applications with Spring Boot 2.2 and React JS Step-by-step guide to design and develop intuitive full stack web applications by Dinesh Rajput (z-lib.org)

*
OAuth Config
*
security.oauth2.client.access-token-uri=http://localhost:8282/prodos
auth
srvr/oauth/tokensecurity.oauth2.client.user-authorization-
uri=http://localhost:8282/prodos
auth
srvr/oauth/authorize
security.oauth2.client.client-id=dineshonjava
security.oauth2.client.client-secret=dineshonjava
As you can see, we configured the access token URI and user authorization URI. The client application will provide the username and password to
the Auth server application to get the access token and this token is used to pass the resource server to get the protected resource.
Let’s see the following controller class that is responsible to get the access token from the Auth server:
package com.dineshonjava.prodos.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.dineshonjava.prodos.service.AuthService;
@RestController
public class AuthController {
   @Autowired
   AuthService authService;
   @GetMapping(value = “/prodos-auth”)
   public String getAccessToken(@RequestParam String username, @RequestParam String password, ModelMap model) {
   String accessToken = null;
   accessToken = authService.generateAccessToken(username, password);
   return accessToken;
   }
}
As you can see in the preceding code, the controller class has the Autowired dependency with the AuthService class as shown in the following
code:
package com.dineshonjava.prodos.service;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.dineshonjava.prodos.dto.AuthResponseDto;
import com.fasterxml.jackson.databind.ObjectMapper;
@Service
public class AuthService {
   private static final Logger logger = LoggerFactory.getLogger(AuthService.class);
   @Autowired
   private RestCallService restCallService;
   @Value(“${security.oauth2.client.access-token-uri}”)
   private String ACCESS
TOKEN
API
DOMAIN
URI;
   @Value(“${security.oauth2.client.client-id}”)
   private String ACCESS
TOKEN
API
CLIENT
ID;
   @Value(“${security.oauth2.client.client-secret}”)
   private String ACCESS
TOKEN
API
CLIENT
SECRET;
   public String generateAccessToken(String username, String password) {
   String response = null;
   Map params = new HashMap();
   params.put(“username”, username);
   params.put(“password”, password);
   params.put(“grant_type”, “password”);
   String auth = ACCESS
TOKEN
API
CLIENT
ID+”:”+ACCESS
TOKEN
API
CLIENT
SECRET;
   try {
   response = restCallService.restTemplatePost(ACCESS
TOKEN
API
DOMAIN
URI, params, auth);
   } catch (Exception e) {
   logger.error(“Exception while calling access token API:{} “, e.getMessage());
   }
   if (!StringUtils.isEmpty(response)) {
   ObjectMapper mapper = new ObjectMapper();
   try {
   AuthResponseDto authResponseDto = mapper.readValue(response, AuthResponseDto.class);


   response = authResponseDto.getAccess_token();
   } catch (IOException e) {
   e.printStackTrace();
   }
   }
   return response;
   }
}
The preceding AuthService class is responsible to get the tokens generated by the Auth server. We are not going to explain all the classes of the
client application in this book. You can find the complete source code for the client application from GitHub at https://github.com/dineshonjava/bpb-
spring-boot-reactjs .
Now, run the client application and access the homepage of the client application in the browser. It will render a login page. You need to provide
credentials here:
Figure 5.19: The client application login page
Let’s provide appropriate credentials and then you will be redirected to the homepage as shown in the following screenshot:
Figure 5.20: The client application login page
Now, the client application has the access token generated by the Auth server application. Let’s make a call to the resource server by clicking on


the Access all Products link as shown in the following screenshot:
Figure 5.21: The client application login page
In the preceding screenshot, the page rendered all the products fetched from the resource server application. Let’s see the following source code
for a method that will be used to fetch the protected resource from the resource server:
public String findAllProducts(ModelMap model) {
   String accessToken = authService.generateAccessToken(“dinesh”, “mypass”);
   HttpHeaders headers = new HttpHeaders();
   headers.setContentType(MediaType.APPLICATION_JSON);
   headers.set(“Authorization”, “Bearer “ + accessToken);
   HttpEntity entity = new HttpEntity<>(“parameters”, headers);
   List products = restTemplate.exchange(BASE_URL+”/products”, HttpMethod.GET, entity, List.class).getBody();
   model.put(“products”, products);
   return “products”;
   }
As you can see in the preceding source code, first we used AuthService to receive an access token for a given user (username: dinesh and
password: mypass). We set this token to the Header as the Bearer token. Then, we made a call to the resource server using the exchange()
method of the RestTemplate object.
Finally, we can get the product list as a resource from the resource server. In this chapter, we created the applications to secure your REST APIs.
But OAuth2 is one of most widely used authentication mechanisms. Even Spring Security provides an exhaustive support to the other
authentication mechanism.
Conclusion
In this chapter, we discussed the Spring Security auto-configuration in our RESTful application. We implemented the HTTP basic authentication in
our PRODOS RESTful application. But the HTTP basic authentication is not appropriate for the production application and a large number of
users.
We also implemented Spring Security with the JWT token mechanism. We secured our REST APIs with Spring Security and the JWT
authentication, which is a lightweight authentication method suitable for our needs.
OAuth2 is the most widely used authentication mechanism to secure your REST APIs. In this chapter, we implemented OAuth2 and Spring Security
with the JWT. We created three separate applications such as Prodos OAuth Server , Prodos Resource Server , and Prodos Client-Server
application.


In the next Chapter 6: Testing Spring Boot Application , we will discuss how to test our REST services using Spring Boot.
Questions
What is Spring Security?
What is the delegating filter proxy?
What is the security filter chain?
How to use in-memory user store configuration?
How to use the JDBC user store configuration?
How to use an LDAP user store configuration?
How to create the custom user details service configuration?
What is password encoding?
What is the security context?
How is a principal defined?
What are authentication and authorization? Which should come first?
How to use JWT?
What is OAuth2?
Chapter 6
Testing a Spring Boot Applicatio
Once you have created the product, then testing of the product is also an important part. Testing and test cases are a crucial part for your
application; test cases do not only verify your code but also make sure that your application works as per your expectations. In this chapter, we will
explore testing modules of Spring Boot and we will learn how to test a Spring Boot application using the unit testing and integration testing. You will
learn to unit test Spring Boot services and also learn to mock Spring Boot services.
Spring Boot does not provide any specific module to write unit tests for an application. Spring Boot provides the integration testing module for your
application because the Spring framework does bean wiring between the application components in your Spring application. You can use this
module to write integration tests to test whether each component of your Spring application is properly configured and created. But for the unit test
cases, you can use the JUnit library in your application.
In this chapter, we will start by adding a testing module to your Spring application (the PRODOS application as we have used throughout all
chapters) and this module enables an application context for your testing environment. In this chapter, we will discuss the following topics:
Testing in Spring Boot
Creating unit tests
Creating integration tests
o Testing the controllers
o Testing auto-configured data JPA repository
o Testing authentication controllers
Loading test configurations
Activating profiles for a test class
Testing in Spring Boot
The Spring framework provides us with a separate module for testing the Spring application, that is, Spring test. This module provides the testing
runner class that helps to load a Spring application context in JUnit-based application tests. But with Spring Boot, it is very easy to add the testing


framework, by default; Spring Boot enables the testing framework.
Let’s take a look at your pom.xml file. The Spring Boot test starter can be added to your application pom.xml file as shown in the following code:
   org.springframework.boot
   spring-boot-starter-test
   test
The preceding Maven dependency adds the Spring Boot test starter to your application. It provides us with a lot of handy libraries for testing such
as JUnit, Mockito, AssertJ, and more. Also, the Spring Boot Initializr creates a separate source folder as the names test and adds an initial testing
application class to this source folder, as shown in the following screenshot:
Figure 6.1: Test Sorce folder created in the Spring Boot Application
In the preceding screenshot, the src/test/java source folder is created and you can see a ProdosApplicationTests test class. The following code is
created by default:
package com.dineshonjava.prodos;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProdosApplicationTests {
   @Test
   public void contextLoads() {
   }
}
As you can see, the previous generated test class is annotated with the @SpringBootTest annotation. This annotation enables the Spring test
modules in your application. The @SpringBootTest annotation provides the following features:
It uses SpringBootContextLoader as the default ContextLoader.
This annotation automatically searches for the configuration files annotated with the @SpringBootConfiguration annotation.
It also allows you to customize the Environment properties using the properties attribute.
This annotation allows you to customize different webEnvironment modes such as the ability to start a fully running web server by listening on a
defined or random port.


In the REST consumer applications, this annotation registers a TestRestTem-plate and/or WebTestClient bean for use in web tests.
If your test is @Transactional, by default, the Spring Boot test framework rolls back all the transactions at the end of each test method. And the
Spring Boot test framework frame uses an in-memory database such as H2, HSQL, and so on.
Testing is an important part of software development. The Spring Initializr gives you a test class to get started with. Let’s start with the unit testing
of the application.
Creating unit tests
Unit tests are very important for your application. Unit testing tests one unit of functionality and the unit test does not require any external
dependencies. You can simply create stubs or mock objects for external classes because external dependencies are not available since we are
testing a unit.
So, in unit testing, you can use the fake object or stub implementation of the original object to resolve the external dependencies. The external
dependencies cannot be a show stopper for unit testing. There are many frameworks available that provide mocking objects such as Mockito,
jMock, and EasyMock. Let’s see the following diagram related to the external dependencies in the unit testing of a controller class:
Figure 6.2: Stub implementation of ProductRespository in unit testing
In the preceding diagram, you can see both modes of your application, the production mode and unit test mode. In the production mode, the
Spring framework injects all the required external or internal dependencies with the controller class using the Spring configuration class. But in the
unit testing mode, the Spring framework does not play any role. Here, we create a stub object of the product repository that is provided to the
controller class. The stub object of the ProductRespository class does not make any connection to the database. The stub object has own dummy
data for testing.
In this example, I want to create a unit test for the ProductController class and test two methods, findProductById() and findAllProducts().
The findProductById() method will return the product object associated product ID and findAllProducts() will return the list of products.
Let’s create the ProductController class and test this class with unit testing:
package com.dineshonjava.prodos.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;


import org.springframework.web.bind.annotation.RestController;
import com.dineshonjava.prodos.domain.Product;
import com.dineshonjava.prodos.repository.ProductRepository;
@RestController public class ProductController {
   private ProductRepository productRepository;
   public ProductController(ProductRepository productRepository) {
   super();
   this.productRepository = productRepository;
   }
   @GetMapping(value = “/products”, produces = {MediaType.APPLICATION
JSON
VALUE})
   public List findAll(){
   List products = new ArrayList<>();
   productRepository.findAll().forEach(i -> products.add(i));
   return products;
   }
   @GetMapping(value = “/products/{id}”, produces = {MediaType.APPLICATION
JSON
VALUE})
   public Product findProductById(@PathVariable String id){
   return productRepository.findById(id).isPresent() ? productRepository.findById(id).get() : null;
   }
}
The preceding ProductController class has a dependency on the ProductRepoistory implementation. Let’s now create a stub implementation of the
ProductRepository class for unit testing the ProductController class:
public class StubProductRepository implements ProductRepository {
...
   @Override
   public Account findProductById(String id) {
   return new Product(“MOB301”, “POCO”, “Mobile”, “Xiomi Smart Phone with 24MP front camera”, “Xiomi”);
   }
   @Override
   public List findAll() {
   List products = new ArrayList<>();
   products.add(new Product(“MOB302”, “OPPO F6”, “Mobile”, “OPPO Smart Phone with 24MP front camera”, “OPPO”));
   products.add(new Product(“MOB303”, “VIVO V15”, “Mobile”, “VIVO Smart Phone with 24MP front camera”, “VIVO”));
   return products;
   }


   ...
}
The StubProductRepository class is a stub implementation of ProductRepository, by implementing methods with dummy data without calling the
actual database. Let’s take a look at the following diagram that explains the two implementations of ProductRepository:
Figure 6.3: JPA and Stub implementation of ProductRepository
In the preceding diagram, you can see two implementations of the ProductRepository class available in the application, that is,
JpaProductRepository and StubProductRepository. The StubProductRepository is used for unit testing without integrating the database
dependency. Let’s take a look at the following ProductControllerTests unit test class using the stub repository:
com.dineshonjava.prodos
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import com.dineshonjava.prodos.repository.StubProductRepository;
public class ProductControllerTests {
   ProductController productController;
   @Before
   public void setUp() {
   productController = new ProductController( new StubProductRepository() );
   }
   @Test
   public void testFindProductById() {
   assertTrue(productController.findProductById(“MOB01”).getType().equals(“Mobile”));
   }
   @Test
   public void testFindAll() {
   assertFalse(productController.findAll().size() == 5);
   }
}


In the preceding test class of the controller, we have three methods. The setup() method creates an object of the ProductController class, and this
method is annotated with the @Before annotation. That means JUnit will call this method before the test methods execute. The other two methods,
testFindProductById() and testFindAll(), are annotated with the @Test annotation, which indicates that these are test methods.
We discussed how to write the unit tests for any class in your application. The unit tests are easy to implement and understand. The unit tests of
stub classes are reusable. But any change in the interface will force you to make the same changes in the stub implementation of the same
interface.
The Spring framework provides support to integration testing in your Spring application. Let us see how Spring provides support to integration
testing in the next section.
Creating integration tests
In integration testing, we test the interactions of multiple components of the application working together. In contrast to unit testing, integration
testing makes sure that all internal or external dependencies work fine. So, integration testing also ensures all components perform as per
expectations, including all dependencies. The Spring framework provides support to resolve these dependencies, which is similar to the production
application. Let us see the following diagram about the integration testing:
Figure 6.4: Components in integration testing
As you can see in the preceding diagram, ProductControllerTests is using the actual ProductRepository implementation instead of its stub or mock
implementation we have used in the unit tests. Also, the AccountRepository class uses data from the database instead of using the dummy data we
have used in unit testing.
Spring Boot provides a separate testing module (spring-test.jar) for integration testing and consists of several JUnit test-support classes. Spring
has a central support class, which is SpringRunner. It caches a shared ApplicationContext across test methods.
Let’s see the following class with integration testing.
Testing the controllers
Spring provides some powerful support for testing and makes it possible to test a web application easily. Let us start with a simple controller class
with the single request handler method. So, we will write a test class for this controller class, and create a test method to perform an HTTP GET
request for the root path / and expect successful results with the returned content that contains the phrase Hello World!!!. Let’s take a look at the
following testing class for the HomeController class:
package com.dineshonjava.prodos;
import static org.hamcrest.Matchers.containsString;
import static


org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
   @Autowired
   private MockMvc mockMvc;
   @Test
   public void testHome() throws Exception {
   mockMvc.perform(get(“/”))
   .andExpect(status().isOk())
   .andExpect(content().string(
   containsString(“Hello World!!!”)));
   }
}
Run the test case and check whether the STS JUnit tab tests were passed:
Figure 6.5: Showing successful test execution
Let’s create the tests for your product controller as shown in the following code snippet:
package com.dineshonjava.prodos;
//imports
@RunWith(SpringRunner.class)
@WebMvcTest(ProductController.class)


public class ProductControllerTests {
   @Autowired
   private MockMvc mockMvc;
   @Autowired
   private ProductRepository productRepository;
   ...
   ...
}
The preceding test class, ProductControllerTests, is annotated with the @WebMvcTest annotation. We can use this annotation with
@RunWith(SpringRunner.class) for the Spring MVC tests. This annotation can be used when you want to test only the Spring MVC components.
We have passed the ProductController class as an argument of this annotation to expose the endpoints of ProductController.
The @WebMvcTest annotation disables all the auto-configuration of your application and enables only relevant configurations to MVC tests such
as @Controller, @ ControllerAdvice, @JsonComponent, and so on. Other than this, the classes annotated with @Component, @Service, or
@Repository annotations will not be available in the application context.
By default, the @WebMvcTest annotation auto-configures Spring Security and MockMvc. You can use the @AutoConfigureMockMvc annotation to
control MockMVC.
Let’s add the first test case to test the /products/{ID} endpoint of the ProductController class:
@Test
public void testFindProduct() throws Exception {
   String expected = “{id: \”MOB01\”,name: \”Samsung A6 plus\”,type: \”Mobile\”,description: “
   + “\”Samsung A6 plus is very nice phone with 24mp front camera\”,brand: \”Samsung\”}”;
   mockMvc.perform(get(“/products/MOB01”))
   .andExpect(status().isOk())
   .andExpect(content().json(expected));
}
We will add another test case to create a new product to the database using the HTTP POST request to the /products endpoint:
@Test
public void testPostProduct() throws Exception {
   String newProduct = “{\”id\”: \”MOB05\”,\”name\”: \”Samsung A6 plus\”,\”type\”: \”Mobile\”,\”description\”: “
   + “\”Samsung A6 plus is very nice phone with 24mp front camera\”,\”brand\”: \”Samsung\”}”;
   mockMvc.perform(post(“/products”)
   .accept(MediaType.APPLICATION

Download 8,6 Mb.

Do'stlaringiz bilan baham:
1   ...   5   6   7   8   9   10   11   12   ...   37




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish