Total Pageviews

Showing posts with label JUnit. Show all posts
Showing posts with label JUnit. Show all posts

2020/12/01

[Java] [JUnit] [SpringBoot] How to assign active profile in unit test?

Requirement
If I have multiple profiles in Spring Boot project, how to assign specific profile in my unit test program?


How-To
Added @ActiveProfiles onto your unit test class:
package com.test.tool.filegenerator.ftl.cp937;

import com.test.tool.filegenerator.util.Cp973FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("office")
public class TS0110_050110_70118_R01FileTest {

    @Autowired
    private Cp973FileUtils cp973FileUtils;

    @ParameterizedTest
    @ValueSource(strings = {"delivery/test data/LN3112P2.LN3112P2"})
    public void testReadTS0110_050110_70118_R01(String file) {
        Assertions.assertThatCode(
                () -> cp973FileUtils.readAndPrintContent(file)).doesNotThrowAnyException();
    }

}


2017/10/04

How to Improve Code Coverage in Enumeration Type ?

Problem
Assume I have a enumeration as bellows:
package albert.practice.designPattern.factory;

public enum ShapeEnum {
    CIRCLE, RECTANGLE, SQUARE, TRIANGLE, OVAL;
}


After I run code coverage test, the coverage rate in enumeration is low:


How to improve its code coverage rate?




How-To
To get rid of this issue, you need to call the values() methods in this enumeration. You can check the testShapeEnum() in the test code:
package albert.practice.designPattern.factory;

import static org.junit.Assert.assertEquals;

import java.util.function.Supplier;

import org.junit.Test;

public class ShapeFactoryTest {

    @Test
    public void testDifferentShape() {
        Supplier<ShapeFactory> shapeFactory = ShapeFactory::new;
        shapeFactory.get().getShape(ShapeEnum.CIRCLE).draw();
        shapeFactory.get().getShape(ShapeEnum.RECTANGLE).draw();
        shapeFactory.get().getShape(ShapeEnum.OVAL).draw();
        shapeFactory.get().getShape(ShapeEnum.SQUARE).draw();
        shapeFactory.get().getShape(ShapeEnum.TRIANGLE).draw();
    }

    @Test
    // https://stackoverflow.com/questions/4512358/emma-coverage-on-enum-types/4548912#4548912
    public void testShapeEnum() {
        ShapeEnum[] shapeEnums = ShapeEnum.values();
        assertEquals(5, shapeEnums.length);
    }

}







2017/08/10

How to Improve Code Coverage After Using Apache Lombok?

Problem
After using Project Lombok, we can find out it help use reduce our boilerplate code. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package albert.practice.lambda;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.google.common.base.Strings;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

public class LambdaTest {

    public List<Person> filterData() {
        List<Person> people = createData();
        return people.stream().filter(p -> p.age >= 35).filter(p -> !Strings.isNullOrEmpty(p.email))
                .collect(Collectors.toList());
    }

    public List<Person> filterDataWithSort() {
        List<Person> people = createData();
        return people.stream().filter(p -> p.age >= 35).sorted((p1, p2) -> (p1.age - p2.age))
                .sorted((p1, p2) -> p2.name.compareTo(p1.name)).collect(Collectors.toList());
    }

    public List<Person> createData() {
        Person ben = new Person("Ben Whittaker", 70, "ben@gmail.com");
        Person jules = new Person("Jules Ostin", 30, "jules@gmail.com");
        Person fiona = new Person("Fiona Farwell", 68, null);
        Person matt = new Person("Matt", 35, "matt@gmail.com");
        
        return Arrays.asList(ben, jules, fiona, matt);
    }

    @Data
    @ToString
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Person {
        private String name;
        private int age;
        private String email;
    }

}

But you will also notice your code coverage rate is down dramatically.


How to improve the code coverage rate?


How-To
Add two dependencies to your pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<dependencies>
    <dependency>
        <groupId>org.meanbean</groupId>
        <artifactId>meanbean</artifactId>
        <version>2.0.2</version>
    </dependency>

    <dependency>
        <groupId>nl.jqno.equalsverifier</groupId>
        <artifactId>equalsverifier</artifactId>
        <version>2.2.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Check the testPersonBean() and testEqualsAndHashCode() in this test case:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package albert.practice.lambda;

import static org.junit.Assert.assertEquals;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.meanbean.test.BeanTester;

import albert.practice.lambda.LambdaTest.Person;
import lombok.extern.slf4j.Slf4j;
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;

@Slf4j
public class LambdaUnitTest {

    private LambdaTest lambdaTest = null;

    @Before
    public void setup() {
        lambdaTest = new LambdaTest();
    }

    @Test
    public void testCreateData() {
        List<Person> people = lambdaTest.createData();
        assertEquals(people.size(), 4);
    }

    @Test
    public void testFilterData() {
        List<Person> people = lambdaTest.filterData();
        log.debug("testFilterData = " + people.toString());
        assertEquals(people.size(), 2);
    }

    @Test
    public void testFilterDataWithSort() {
        List<Person> people = lambdaTest.filterDataWithSort();
        log.debug("testFilterDataWithSort = " + people.toString());
        assertEquals(people.size(), 3);
    }

    // Testing getter and setters methods
    @Test
    public void testPersonBean() {
        new BeanTester().testBean(LambdaTest.Person.class);
    }

    // Testing equals() and hashCode()
    @Test
    public void testEqualsAndHashcode() {
        EqualsVerifier.forClass(LambdaTest.Person.class)
                .suppress(Warning.STRICT_INHERITANCE, Warning.NONFINAL_FIELDS).verify();
    }

}

After running code coverage analysis, you can find out this problem had been solved:




Reference
[1] http://www.jdev.it/tips-unit-testing-javabeans/

2017/06/08

[Eclipse] EclEmma - Java Code Coverage for Eclipse

In computer science, code coverage is a measure used to describe the degree to which the source code of a program is executed when a particular test suite runs. A program with high code coverage, measured as a percentage, has had more of its source code executed during testing which suggests it has a lower chance of containing undetected software bugs compared to a program with low code coverage.

EclEmma is a free Java code coverage tool for Eclipse, it brings code coverage analysis directly into the Eclipse workbench.


Prerequisite
Prepare your unit test programs:



Execution
After you installed EclEmma Plugin, you can run  Coverage as => JUnit Test


Then you can get the converge analysis report


Summary
While 100% code coverage is nice, it's not a good metric to blindly follow. 100% code coverage doesn't tell you anything other than you have tests that execute all your lines of code. Your code can still have bugs if that covered code does the wrong thing or doesn't do enough. 


Reference
[1] https://en.wikipedia.org/wiki/Code_coverage
[2] http://www.eclemma.org/
[3] https://stackoverflow.com/questions/26360245/try-with-resource-unit-test-coverage


2014/12/09

How to mock autowired fields via Mockito

Problem
Assume we wrote a calculation service which provide add and subtract service.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;

/**
 * The Class CalculationService.
 */
@Service
@Slf4j
public class CalculationService {

    public int add(int num1, int num2) {
        return num1 + num2;
    }
    
    public int subtract(int num1, int num2) {
        return num1 - num2;
    }
    
}

If we would like to do unit test for CalculationService class, and autowire CalculationService into service class as bellows:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import static org.junit.Assert.assertEquals;
import gov.nta.nss.service.CalculationService;

import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

public class CalculationServiceTest {

    /* Inject CalculationService */
    @Autowired
    private CalculationService service;

    /* Test add function in CalculationService */
    @Test
    public void testAdd() {
        // arrange & act
        int result = service.add(6, 5);

        // assert
        assertEquals(11, result);
    }

    /* Test subtract function in CalculationService */
    @Test
    public void testSubtract() {
        // arrange & act
        int result = service.subtract(6, 5);

        // assert
        assertEquals(1, result);
    }

}

As I executed this test class, it returned NullPointerException. This exception result from failed to autowire CalculationService. How to overcome this problem?



Solution
We can mock autowired fields by Mockito to solve this problem. Here is the revised test code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import static org.junit.Assert.assertEquals;
import gov.nta.nss.service.CalculationService;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;

public class CalculationServiceTest {

    /* Inject CalculationService */
    @InjectMocks
    private CalculationService service;

    /* Initialized mocks */
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    /* Test add function in CalculationService */
    @Test
    public void testAdd() {
        // arrange & act
        int result = service.add(6, 5);

        // assert
        assertEquals(11, result);
    }

    /* Test subtract function in CalculationService */
    @Test
    public void testSubtract() {
        // arrange & act
        int result = service.subtract(6, 5);

        // assert
        assertEquals(1, result);
    }

}

Test result is bellowing:


Reference
[1] http://lkrnac.net/blog/2014/01/mock-autowired-fields/
[2] http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html


2014/11/07

JUnit Quick Start

Assume I has one utility class, which provide some services, including find employee name, find all employees, etc.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class MyUtils {  
  /**  
   * Checks for this employee.  
   *   
   * @param name  
   *      the name  
   * @return true if find data; false if find nothing  
   */  
  public static Boolean hasThisEmployee(final String name) {  
     Boolean hasData = Boolean.FALSE;  
     List strs = initData();  
     hasData = findData(name, hasData, strs);  
     return hasData;  
   }  
   /**  
    * Find employee.  
    *   
    * @param name  
    *      the name  
    * @return employee name if find; null if not find  
    */  
   public static String findEmployee(String name) {  
     Boolean hasData = Boolean.FALSE;  
     List strs = initData();  
     hasData = findData(name, hasData, strs);  
     String employee = null;  
     if(hasData) {  
       employee = name;  
     }  
     return employee;  
   }  
   /**  
    * Find all employee.  
    *   
    * @return list of String  
    */  
   public static List findAllEmployee(){  
     return initData();  
   }  
   /**  
    * Find employee.   
    *   
    * @param name  
    * @param hasData  
    * @param strs  
    * @return true if find data; false if find nothing  
    */  
   private static Boolean findData(final String name, Boolean hasData, List strs) {  
     Predicate predicate = new Predicate() {  
       @Override  
       public boolean apply(String input) {  
         return name.equalsIgnoreCase(input);  
       }  
     };  
     Iterator iterator = Collections2.filter(strs, predicate).iterator();  
     while (iterator.hasNext()) {  
       if (!Strings.isNullOrEmpty((String) iterator.next())) {  
         hasData = Boolean.TRUE;  
         break;  
       }  
     }  
     return hasData;  
   }  
   /**  
    *   
    * @return initial data  
    */  
   private static List initData() {  
     List strs = new ArrayList<>();  
     strs.add("Albert");  
     strs.add("Mandy");  
     strs.add("Eric");  
     return strs;  
   }  
 }  


If we would like to do unit test, this unit test class will demonstrate how to use assertSame, assertNotNull, and assertArrayEquals. 
All test methods are annotated with @Test

Here is a template for writing JUnit4-style tests:
package com.example.foo;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link Foo}.
 *
 * @author user@example.com (John Doe)
 */
public class FooTest {

    @Test
    public void thisAlwaysPasses() {

    }

    @Test
    @Ignore
    public void thisIsIgnored() {
    }
}

And we will demonstrate some assert methods, including

  • assertArrayEquals(java.lang.Object[] expecteds, java.lang.Object[] actuals) : 
    • Asserts that two object arrays are equal.
  • assertSame(java.lang.Object expected, java.lang.Object actual) :  
    • Asserts that two objects refer to the same object.
  • assertNotNull(java.lang.Object object) : 
    • Asserts that an object isn't null.
  • assertEquals(long expected, long actual) : 
    • Asserts that two longs are equal.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class FooTest {  
  /**  
   * Test assert same.  
   * The list includes Albert, Mandy, Eric, and Obama,  
   * it should return True if I use "Albert" to search  
   */  
  @Test  
  public void testAssertSame() {  
    assertSame(Boolean.TRUE, MyUtils.hasThisEmployee("Albert"));  
   }  
   /**  
    * Test assert not null.  
    * The list includes Albert, Mandy, Eric, and Obama,  
    * it should return not null if I use "Mandy" to search  
    */  
   @Test  
   public void testAssertNotNull() {  
     assertNotNull(MyUtils.findEmployee("Mandy"));  
   }  
   /**  
    * Test assert array equals.  
    * The list includes Albert, Mandy, Eric, and Obama,  
    * so it should return equal  
    */  
   @Test  
   public void testAssertArrayEquals() {  
     List strs = new ArrayList<>();  
     strs.add("Albert");  
     strs.add("Mandy");  
     strs.add("Eric");  
     assertArrayEquals(strs.toArray(), MyUtils.findAllEmployee().toArray());  
   }  
 } 

If all tests are executed as expected, then you will see success result


If some test does not execute as expected, then you will see fail result

Aggregating tests in suites
If you would like to run multiple test classes at the same time, you can do this way
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 import org.junit.runner.RunWith;  
 import org.junit.runners.Suite;  
 import org.junit.runners.Suite.SuiteClasses;  
 @RunWith(Suite.class)  
 @SuiteClasses({  
   FooTest.class,  
   FooTest2.class  
 })  
 public class TestSuite {  
    // the class remains empty,  
    // used only as a holder for the above annotations  
  }  
 

There are two test case class (FooTest.class, FooTest2.class) in the test suite. In the test result, you can see it will run all test cases in FooTest.class and FooTest2.class


Ignore Test
If for some reason, you just want it ignored, you temporarily disable a test. You just need to add @Ignore annotation
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 public class FooTest2 {  
   @Test  
   @Ignore  
   public void testAssertEqual() {  
     assertEquals(36, MySecondUtils.getAge(1978));  
   }  
   @Test  
   public void testEquals() {  
     assertEquals("Pass", MySecondUtils.getExamResult(88));  
    }  
    @Test  
    public void testAssertThat() {  
      assertThat(MySecondUtils.getExamResult(88).equals("Pass"));  
    }  
  }  
 


See.... testAssertEqual method had been ignored.




Reference
[1] https://github.com/junit-team/junit/wiki

2008/06/29

Applied MyEclipse and JUnit to do Hibernate Code Gen and Testing

• Hibernate Code Generation
• Code Gen Process
• Generate DAO for the four tables
• Artifacts
• Spring Configuration File
• Apply JUnit to do DAOs Test
• JUnit Framework
• How to Test with JUnit?
• Simplified Workflow of Applying JUnit
• Testing Process
• Generate Unit Test Result via Ant

http://www.slideshare.net/junyuo/applied-myeclipse-and-junit-to-do-hibernate-code-gen-and-testing/