Thursday, February 27, 2020

Springboot Naming convention of properties and YAML file and profiles


Let’s say your application can work with 3 different types of databases
o   H2 (Local Development)
o   Mysql (Development environment)
o   Mysql (Production environment)
o   And you want to utilize only related settings when you are doing the development/testing/production debugging.
o    You can actually create three different application.properties files and use the naming convention which will later used to load the specific profile.
o   So for the given case put below 3 files under your resources folder
§  application-default.properties
§  application-dev.yaml
§  application-prod.yaml
§  The above files can be found in the given github project
o   And when you will run the project with “dev” profile , all your settings will be loaded from application-dev.yml.
o   Notice here convention is used on configuration and we didn’t need to specify any profiles or which property/yaml file to load in case if a profile is active.
o   Example project
o   Note : We used SpringBoot defaults here for us to do a lot of things , we didn’t need to define a spring bean for datasource configuration , also we used convention and created those property and yaml files to be loaded in case a specific profile is loaded.
o   Also please note we have only used properties and yaml combination to show you how to use both in combination , you can use all properties or all yaml files.

Tuesday, February 25, 2020

Duplicating a github repository


Follow below steps to duplicate your repository
  •   Create your new  repository called "my_new_repository"
  • Create a clone of your repository  
                     git clone https://github.com/user_name/my_old_repository.git
  • cd my_old_repository
  • Push mirror to new repository 
                   git push --mirror https://github.com/user_name/my_new_repository.git
·                           cd ..
  •  Remove old git
                rm -rf my_old_repository.git 
 
And here you go.

Friday, February 7, 2020

TDD , Automated Test Development using JUNIT5


Types of automated testing
In general, automated tests fall into one of the following categories, from fastest to slowest:
 Unit tests: These typically test a single method, class, or function in isolation, providing assurance to the developer that their code operates as designed. For many reasons, including the need to keep our tests fast and stateless, unit tests often “stub out” databases and other external dependencies (e.g., functions are modified to return static, predefined values, instead of calling the real database).

Acceptance tests: Humble and Farley define the difference between unit and acceptance testing as, “The aim of a unit test is to show that a single part of the application does what the programmer intends it to....The objective of acceptance tests is to prove that our application does what the customer meant it to, not that it works the way its programmers think it should.”
After a build passes our unit tests, our deployment pipeline runs it against our acceptance tests. Any build that passes our acceptance tests is then typically made available for manual testing (e.g., exploratory testing, UI testing, etc.) as well as for integration testing.
Integration tests: Integration tests are where we ensure that our application correctly interacts with other production applications and services, as opposed to calling stubbed out interfaces.

Kim, Gene. The DevOps Handbook: . IT Revolution Press

We will cover Unit testing using JUNIT5 in this post

Download Junit5 from below link


Unit Testing Using Junit5:
JUnit 5 is the next generation of JUnit. The goal is to create an up-to-date foundation for developer-side testing on the JVM.




Useful Annotations And Classes
@BeforeEach

This method in test class will be executed before each test case and can be used to prepare data needed to run the test cases.
@Test

This annotation will mark a test method as a test case.
@Mock

This annotation is used to create mock for Services,Repositories etc.
@ExtendWith(MockitoExtension.class)

This method initiates all mocks
MockMvc

Mock MVC is utility by spring which helps us test the controllers by initiating HTTP requests.
org.mockito.when (Static)

This static method is used to create mock interections, such as when a specific method of a service is called. An example will be shown later.
org.mockito.then
This static method is used with the when operation. See the coding example below.
org.mockito.verify
This static method is used to verify that during the execution of test how many times a particular method has been called e.t.c.


Best Practice for writing  test Using BDD Technique
·       Write Test cases using the below pattern
o   Given : A Data Set
o   When : When a function is called
o   Then : what should happen / returned



Examples Of JUNIT5 Test Cases for Controller and Services are given below :

Controller Get Method to Test

@RequestMapping("/recipe/{id}/show")

public String showRecipe(@PathVariable String id, Model model){

    System.out.println("showRecipe called");

    model.addAttribute("recipe",recipeService.getRecipeById(new Long(id)));

    return "recipe/show";

}

Below test case has been written using Given,When,Then method.
Notice
·       Under Given: we are preparing the data and mock interaction
·       under when : We are calling the Controller service which we want to test.
·       Under Then : we are checking the conditions to verify if the test has been passed or not

Test
@Test

void testGetRecipe() throws Exception {

    //Given

    Recipe recipe=new Recipe();

    recipe.setId(1L);

    MockMvc mockMvc= MockMvcBuilders.standaloneSetup(recipeController).build();

    when(recipeService.getRecipeById(anyLong())).thenReturn(recipe);
   //When

    mockMvc.perform(

            get("/recipe/1/show"))

    //Then

            .andExpect(status().isOk())

            .andExpect(view().name("recipe/show"))

            .andExpect(model().attributeExists("recipe"));

}

Controller Post method to test
Controller Post Method
@PostMapping("/new")
public String processCreationForm(@ModelAttribute @Valid Owner owner,Model model,BindingResult bindingResult){
   
    Owner ownerSaved=
ownerService.save(owner);
    model.addAttribute(
"owner",ownerSaved);
   
return "redirect:/owners/" + ownerSaved.getId();
}

Test
@Test
void processCreationForm() throws Exception {
   
//Given
   
Owner owner=Owner.builder().id(1L).build();
    when(
ownerService.save(any())).thenReturn(owner);
   
//When
   
mockMvc.perform(post("/owners/new"))
           
//Then
           
.andExpect(status().is3xxRedirection())
            .andExpect(model().attributeExists(
"owner"))
            .andExpect(view().name(
"redirect:/owners/1"));

}



Service Method to Test
Service Method
public void deleteRecipeById(Long recipeId){
   
log.debug(">>> RecipeServiceImpl.deleteRecipeById method is called");
   
recipeRepository.deleteById(recipeId);
}

Test
@Test
void testDeleteRecipeById(){
   
//Given
   
Long idToBeDeleted=1L;
   
//When , since the delete method returns void we cant have when here but
    // verify that the delete method was actually called
    
recipeService.deleteRecipeById(idToBeDeleted);

    //Then
   
verify(recipeRepository,times(1)).deleteById(any());
}

 
Encourage TDD development in your organization
I have found TDD to be the best way to develop applications as it gives us a prospective of writing the test first and than write the code to pass it. We think like a user first and than coder which gives us a lot of flexibility. Additionally , TDD is the best way to have test coverage for your code as writing tests afterwords is a tedious and boring job for developers. Moreover, having test cases helps you quickly/automatically test your already written code while you are adding new functionality and exponentially reduces the time spent testing manually.
Advantage in CI/CD
Going forward to CI/CD you will be ready to get your code automatically tested using all these test cases you have been writing using JUNIT5 and your future builds will be more reliable and less error pron.

SpringBoot Project on github utilizing Junit5
You can also fork my below github Spring boot project to see Junit5 in action.