primo-generator-mock-test

Project address: github.com/chenhaoxian…

introduce

Are you still struggling to write a lot of unit tests? Are you still struggling to build the values of the wrapped classes? The mock unit test code automatically generates Maven plug-ins to solve the problem of developers spending a lot of time in unit testing, optimizing the efficiency and testing time of developers.

Note that primo-generator-mock-test does not currently complete all mock tests, so you do not need to modify a single line of code. For now, you need to make some modifications to the code generated by primo-generator-mock-test, such as branch overwriting and assertion usage.

Primo-generator-mock-test is designed to eliminate the need for developers to write a single line of mock test code. Primo-generator-mock-test is designed to reduce the testing burden of developers and focus on business development and iteration

My own use of mock tests, plus my internal tuI use, statistically reduced the number of mock test users by at least 30-50%. (This project is currently being used by several teams in our company, which saves a lot of unit testing time for team members. Please share it here.)

use

1. Rely on plug-ins first:

The latest version

Latest version: 1.0.0

Simplest configuration:


<plugin>
    <groupId>wiki.primo.generator</groupId>
    <artifactId>primo-generator-mock-test-maven-plugin</artifactId>
    <version>(Version Number)</version>
    <configuration>
        <testPackageName>(0.1.0-SNAPSHOT+ supports multiple package names, separated by semicolons (;).)</testPackageName>
    </configuration>
</plugin>
Copy the code

(Use the simplest configuration, it can be used, feel the following instructions too much do not need to look down)

Example:

<plugin> 
    <groupId>wiki.primo.generator</groupId>
    <artifactId>primo-generator-mock-test-maven-plugin</artifactId>
    <version>1.0.0</version> 
        <configuration>
            <testPackageName>wiki.primo.generator.primogeneratormocktestdemo.service.impl</testPackageName> 
        </configuration>
</plugin>
Copy the code

2. Generate test code

Run the Primo-generator-mock-test :test command for the Maven plug-in under the project module that introduced the plug-in

mvn primo-generator-mock-test:test
Copy the code

To download the template file & generate the test class, run MVN primo-generator-mock-test:test

Related configuration:
Specifies the path. The relative path is the root path of the current running project. (the default download path: / SRC/main/resources/test/template) for the first time to run run plug-in primo – generator – a mock – test: test command, the configuration file can be downloaded to the corresponding path.

You can set the name of the configuration file. Run

primo-generator-mock-test. FTL
to set the name of the configuration file. (The default filename is primo-generator-mock-test.ftl)

3. Introduce mock dependencies

The mock test class method generated by the plug-in relies on PowerMock&Mockito, and it is recommended to introduce the following dependencies directly (no dependencies have no effect on the plug-in running)

<dependency>
    <groupId>wiki.primo.generator</groupId>
    <artifactId>primo-generator-mock-test-jar</artifactId>
    <version>1.0.0 - the SNAPSHOT</version>
    <scope>test</scope>
</dependency>

Copy the code

4. In Configuration, configure related properties

In the project name module of the introduced plug-in, you can run the megatron:test command of the plug-in to generate test cases in the corresponding test path.

mandatory

  • <testPackageName>Do not specify the name of the package where the interface resides. You need to specify the name of the package where the implementation class resides. All classes and methods in the package and its subpackages are traversed.

A single class can be configured. For example: a wiki. Primo. Generator. Primogeneratormocktestdemo. Service. Impl. UserServiceImpl. Java note that configuration must be in a single class. Java end.

Unsupported classes:

  • interface
  • The enumeration
  • An abstract class
  • Private class

optional

Note: Jar packages prior to 1.0.0 are not uploaded to the central repository

1.0.0
  • <jsonConfigPath>: json configuration file path, defaultValue = “/ SRC/main/resources/test/template/”
  • <jsonConfigFileName>Json configuration file name,defaultValue = “primo-generator-mock-test.json”
  • <isDownloadTemplateFile>: Indicates whether to download the Template configuration file locally. The default value is true
  • <isDownloadJsonFile>: Indicates whether to download the JSON configuration file to the local PC. The default value is true
While the SNAPSHOT –

  • : indicates the path to download the configuration file


  • : indicates the author name


  • : indicates the name of the downloaded configuration file


  • : Configures whether the testPackageName package retrieves classes under subpackages recursively (default true)


  • : Configures whether to mock out the parent class and non-tested methods of its own test class (default true). The parent/parent method calls need to be called using this. Mock is not supported in current versions

  • < isSetBasicTypesRandomValue > : configuration is set the base value of the type of randomly generated (the default false)


  • : Number of bits to configure the random value of the string (e.g., “10” for 10 random alphanumeric characters)


  • : int/Integer Specifies the range of random values of the type (for example, “0,1000” indicates the range of [0,1000]). If a fixed value is set to “0”, the int value is set to 0.


  • : Set the range of random values of type long/ long (similar to setIntRandomRange)


  • : Configure Boolean/range of Boolean type random values (e.g., “true”/”false” for fixed values, any other values for true and false random values)

Version of the function

0.2.1 – the SNAPSHOT

  • Fix – Fixes a bug where test code cannot be generated under Windows

0.2.0 – the SNAPSHOT

  • Support to configure JSON, using JSON to construct parameter values
    • Only parameter assignments for actual methods are supported. Mock parameter assignments are not currently supported
    • This time, only user-defined values can be configured

The following is a description of the attributes in the JSON configuration:

{
"isOpen": "Enable JSON configuration - default false"."list": [{"scope":"Scope: Global, package, class, method - default global"."scopeValue": Global is not required. Package is the package name. Class is the class name. Method is the method name.."fullyType": "Fully qualified name of type"."value": {"If type=base, the value is fixed to value":"Value"."If type=custom, value key = fastJSON serialized property name":"Value"}}}]Copy the code
  • Delete obsolete configurations
  • Fix – Fixes a bug that failed to download a configuration file when modifying configFileName

Json Configuration Description

  • You can configure the value of a parameter type by configuring JSON
  • Scope: global, package, class, method

Parameter Value Configure priority: Configure < global < package < class < method through plug-in optional attribute.

While the SNAPSHOT –

  • TestPackageName Configures multiple packages and supports line breaks between semicolons and Spaces
  • TestPackageName can be configured with a single implementation class. For example: a wiki. Primo. Generator. Primogeneratormocktestdemo. Service. Impl. UserServiceImpl. Java note that configuration must be in a single class. Java end.
  • External dependencies simply need to introduce primo-generator-mock-test-jar.

0.1.0 from – the SNAPSHOT

  • Mock out methods with the same number of arguments and comment out the code
  • Resolve the mock method parameter name change issue
  • In-memory loading of classes in the in-loader eliminates the need to manually rely on the required classes in the plug-in, that is, configuring third-party dependencies is no longer necessary
  • Do not need network can be run, the original is through the network stream download file, this version has been modified for jar package read
  • Adding a test class directory is configurable

0.0.1

New/Optimized functions

  1. Support for generating test methods from common non-static methods in all classes under the package
  2. A package that supports configuring mocks to replace all methods of the underlying class
  3. Automatic assignment of base and wrapper types is supported
  4. Added support for enumeration parameters
  5. Can be configured to skip the type of parameters, directly configure the package name, will skip all classes in the package construction (used to skip the construction of the interface, directly assign null)
  6. Optimize the fully qualified name as abbreviation, use import package, use the fully qualified name if there are duplicate classes
  7. Support for configuration to choose whether to automatically mock out parent & non-tested methods themselves – default true
  8. Support configuration Entity Basic type Random setting/Use default Value Null a. Random String Length :10 digits and letters, generated using JDK UUID, ensure that the unique B. Short :[0.00,10000.00) e. Double :[0.00,10000.00) f. Random float:[0.00 F,10000.00f) g. Random float:[0.00 F,10000.00f Long :[0L,100000L] g. Random char: digits/letters
  9. Each test class uses a uniform before annotation for mock methods(Considering the mock for each subsequent branch, allowing the mock would result in the branch not being fully covered)
  10. Mock annotated classes with fully qualified names optimized for abbreviation, class imported, repeat class abbreviation, first class using abbreviation, the following class using fully qualified names
  11. Classes under other packages are no longer supported to be configured to mock, all methods of non-test classes are mock, and private methods of test classes are also mock
  12. The test class has been generated and no overwrite generation will be performed
  13. Supports loading and construction of third-party package classes
  14. For some properties that do not have setter methods, set values are also applied; Expectation: Property values that do not have setters are not set
  15. Support string, int, long, Boolean random value range setting
  16. The generated set method contains the attributes of the parent class. (Note that if the parent class is not in the current project, you need to introduce package dependencies in the plug-in.)
  17. New test class methods support appending mock test methods
  18. Supports simultaneous generation of test classes under different packages
  19. The configuration file is no longer needed for initial download. You can run the generate command to automatically check whether the configuration file is downloaded

Schedule other functions

  • The configuration file can be downloaded to the local PC by default
  • Supports log level setting, facilitating user debugging
  • Support if-else to generate multiple mock branch methods
  • Method can be configured in a JSON file
  • Detection code implementation class method coverage percentage view as well as notification to the pin group
  • Simple set construction assignment is supported
  • Mocking static methods is supported, requiring the fully qualified name of the static class to be configured (mocking static methods is not recommended)
  • Mock a private method in a test class. A private method is used to generate mock tests. This method is not supported by default and needs to be configured.
  • If Mock method names are repeated (with different number of parameters) in the same test method, it cannot be distinguished. Mock only for the first method, and duplicate Mock code will be generated. Expectations: Mocks that support methods of the same name
  • Duplicate methods are not supported (with the same number of arguments but different parameter types), resulting in ambiguous mock method references. Expectation: Mock method references are explicit (solved by matching parameter types)
  • Nested custom parameter constructs are not supported; Expectation: Support for multilevel parameter construction
  • Collection construction is not supported; Expectations: Support the construction of collections
  • Mock method return values do not support customization and return NULL. Expectation: Support for custom/generated values of mock return values
  • Does not support Spring custom transaction manager DataSourceTransactionManager mock; Expectations: Mock support for custom transactions
  • Supports multi-stage parameter construction assignment
  • Mocks that support overloaded methods
  • Assertion configuration support
  • Parameter value configuration YML file
  • Generated test methods can be configured to compile errors, forcing developers to take the initiative to unit test

Pay attention to

Configure mock static methods: @runwith (MockitoJUnitRunner. Class) is used by default, and @runwith (PowerMockRunner. Class) is used if mock static methods are configured.

Using PowerMockRunner and MockitoJUnitRunner classes, it is not possible to support automatically injected mocks (such as the generic baseMapper in the generic parent of the Service layer in Mybatis) with attributes in the superclass that are also injected in the service implementation class. This is because the Mock class treats the two classes as separate instances, mocking out only the base class you inject into the Service implementation class, not the Mapper in the service implementation class’s parent class. For example, the Service implementation class


public class WorkFlowServiceImpl extends ServiceImpl<WorkFlowMapper.WorkFlowEntity> implements IWorkFlowService {
    @Autowired
    private WorkFlowMapper workFlowMapper;
    / /...
}
Copy the code

The parent class ServiceImpl:

public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
    @Autowired
    protected M baseMapper;
    / /...
}
Copy the code

When used in WorkFlowServiceImpl:

baseMapper.deleteById("1");
Copy the code

In the Mock test class:


@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PrepareForTest({BeanConvertUtil.class, FieldBaseDto.class})
public class WorkFlowServiceImplTest {
    @InjectMocks
    private WorkFlowServiceImpl workFlowServiceImpl;
    @Mock
    private WorkFlowMapper workFlowMapper;
    / /...
}
Copy the code

Cannot mock out baseMapper instance because baseMapper and workFlowMapper are not the same instance! You can only mock out the workFlowMapper here.

BaseMapper can now be injected again in the implementation class of the Service layer, or mock using PowerMockRunner. Class

Service layer implementation classes do not recommend using the generic base service superclass to call the generic Mapper operation database layer! You can optionally inject Mapper and then call.

Experience with

199 test methods covering a total of 309 tested methods were generated using Primo-generator-mock-test, and only 3 hours of mock optimization was used (only the method with error was optimized, and branch tests were not perfected).

In my previous experience, 199 mock tests take at least several times longer if all goes well when I write them all myself. (This test project is a project using Mybatis -Plus. The implementation class of the Service layer directly uses the parent class method for many methods, resulting in a very troublesome mock and some time delay. Other projects will save more time relatively.)

The test class:

Test method:

Unit coverage data: