jmockdata

repository·master·Indexed 19 days ago

https://github.com/jsonzou/jmockdata

A Java framework for instantiating and randomly initializing Java types or objects with mock data. It supports primitives, strings, enums, collections, and complex custom POJOs using reflection. Version 4.3.0 requires JDK 1.8 or higher. Key features include generic collection mocking via TypeReference, custom data generation using MockConfig and regular expressions, handling of circular and self-referencing dependencies, and extensibility through custom Mocker classes and BeanMockerInterceptor.

Tokens
4.2K
Snippets
10
Records
11
Agent score
18%

What's inside jmockdata

  1. Handle circular and self-referencing dependencies

    master

    JMockData automatically handles complex object relationships:

    1. Circular Dependencies: If Class A references Class B, and Class B references Class A, JMockData ensures the identity is preserved (e.g., axb.getBXA().getAXB() == axb).
    2. Self-References: If a class contains a field of its own type (e.g., parent field in SelfRefData), JMockData will mock it such that the field points back to the same instance (selfRefData.getParent() == selfRefData).
    // Circular Dependency Example
    public class AXB {
      private BXA BXA;
      private String name;
    }
    public class BXA {
      private AXB AXB;
      private String name;
    }
    
    @Test
    public void testCircular() {
       AXB axb = JMockData.mock(AXB.class);
       AXB circularAxb = axb.getBXA().getAXB();
       assertSame(axb, circularAxb);
    }
    
    // Self-Reference Example
    public class SelfRefData {
      private SelfRefData parent;
    }
    
    @Test
    public void testSelf() {
       SelfRefData selfRefData = JMockData.mock(SelfRefData.class);
       assertSame(selfRefData.getParent(), selfRefData);
    }
  2. Install Jmockdata via Maven or Gradle

    master

    To use Jmockdata in your Java project, add the dependency to your build configuration file. The current version is 4.3.0.

    Maven

    Add the following to your pom.xml:

    Gradle

    Add the following to your build.gradle:

    Note: Jmockdata requires JDK 1.8 or higher.

    <!-- Maven -->
    <dependency>
       <groupId>com.github.jsonzou</groupId>
       <artifactId>jmockdata</artifactId>
       <version>4.3.0</version>
    </dependency>
    
    <!-- Gradle -->
    compile group: 'com.github.jsonzou', name: 'jmockdata', version: '4.3.0'
  3. Mock basic types with JMockData.mock()

    master

    You can directly mock primitive types, their wrapper classes, common Java types, and multi-dimensional arrays using JMockData.mock(Class<T> clazz).

    Supported types include:

    • Primitives: byte, boolean, char, short, int, long, float, double.
    • Wrappers: Byte, Boolean, Character, Short, Integer, Long, Float, Double.
    • Common Types: BigDecimal, BigInteger, Date, LocalDateTime, LocalDate, LocalTime, java.sql.Timestamp, String, Enum.
    • Arrays: Multi-dimensional arrays of any of the above types (e.g., int[], int[][]).
    // Basic type mocking
    int intNum = JMockData.mock(int.class);
    int[] intArray = JMockData.mock(int[].class);
    Integer integer = JMockData.mock(Integer.class);
    Integer[] integerArray = JMockData.mock(Integer[].class);
    
    // Common type mocking
    BigDecimal bigDecimal = JMockData.mock(BigDecimal.class);
    BigInteger bigInteger = JMockData.mock(BigInteger.class);
    Date date = JMockData.mock(Date.class);
    String str = JMockData.mock(String.class);
  4. Configure random ranges and exclude fields with MockConfig

    master

    Use MockConfig to customize the data generation process, such as setting value ranges or excluding specific fields.

    Field Pattern Matching

    Fields can be targeted using three wildcard patterns (case-insensitive):

    1. *FieldWord*: Contains the word.
    2. *FieldWord: Ends with the word.
    3. FieldWord*: Starts with the word.

    Configuration Scopes

    • Global Configuration: Use .globalConfig() to set defaults for all mocked objects (e.g., sizeRange, charSeed, or visibility of static/private/protected fields).
    • Field-level Configuration: Use .subConfig("pattern") to apply specific ranges to fields matching a pattern.
    • Class-level Configuration: Use .subConfig(Class.class, "pattern") to apply settings to specific fields within a specific class.
    • Exclusions: Use .excludes("pattern") or .excludes(Class.class, "pattern") to prevent certain fields from being mocked.

    Example Usage

    MockConfig mockConfig = new MockConfig()
        .globalConfig()
        .setEnabledStatic(false)
        .sizeRange(1, 1)
        // Target fields by pattern
        .subConfig("integerNum", "*float*", "double*")
        .intRange(10, 11)
        // Target specific class fields by pattern
        .subConfig(BasicBean.class, "long*", "*date")
        .dateRange("2018-11-20", "2018-11-30")
        // Exclude fields
        .excludes("*List*", "*Set*");
    
    BasicBean bean = JMockData.mock(BasicBean.class, mockConfig);
    MockConfig mockConfig = new MockConfig()
                // 全局配置
                .globalConfig()
                .setEnabledStatic(false);
                .setEnabledPrivate(false);
                .setEnabledPublic(false);
                .setEnabledProtected(false);
                .sizeRange(1,1)
                .charSeed((char) 97, (char) 98)
                .byteRange((byte) 0, Byte.MAX_VALUE)
                .shortRange((short) 0, Short.MAX_VALUE)
    
                // 某些字段(名等于integerNum的字段、包含float的字段、double开头的字段)配置
                .subConfig("integerNum","*float*","double*")
                .intRange(10, 11)
                .floatRange(1.22f, 1.50f)
                .doubleRange(1.50,1.99)
    
                // 某个类的某些字段(long开头的字段、date结尾的字段、包含string的字段)配置。
                .subConfig(BasicBean.class,"long*","*date","*string*")
                .longRange(12, 13)
                .dateRange("2018-11-20", "2018-11-30")
                .stringSeed("SAVED", "REJECT", "APPROVED")
                .sizeRange(1,1)
    
                // 全局配置
                .globalConfig()
                // 排除所有包含list/set/map字符的字段。表达式不区分大小写。
                .excludes("*List*","*Set*","*Map*")
                // 排除所有Array开头/Boxing结尾的字段。表达式不区分大小写。
                .excludes(BasicBean.class,"*Array","Boxing*");
        BasicBean basicBean = JMockData.mock(BasicBean.class, mockConfig);
  5. Mock generic types using TypeReference

    master

    To mock classes with generic type parameters (e.g., GenericData<A, B, C>), use a TypeReference to preserve type information at runtime. This allows JMockData to correctly mock nested collections and maps within the generic structure.

    // Define a generic parent class
    public class GenericData<A, B, C> {
      private A a;
      private List<B> bList;
      private Map<A, B> map;
    }
    
    @Test
    public void testGenericData() {
        GenericData<Integer, String, BasicBean> genericData = JMockData.mock(new TypeReference<GenericData<Integer, String, BasicBean>>() {});
        assertNotNull(genericData);
    }
  6. Define BeanMockerInterceptor to intercept bean mocking

    master

    Implement the BeanMockerInterceptor interface to intercept the mocking process and change behavior. This is useful for excluding specific fields or providing custom values.

    Interceptor Return Types (InterceptType):

    • InterceptType.UNMOCK: Do not mock this field (excludes it from mocking).
    • InterceptType.MOCK: Allow JMockData to perform automatic mocking.
    • Other values: The returned value will be injected into the field via reflection.

    Registration:

    • Global Interceptor: .registerBeanMockerInterceptor(new BeanMockerInterceptor() {...})
    • Type-specific Interceptor: .registerBeanMockerInterceptor(SimpleBean.class, new BeanMockerInterceptor<SimpleBean>() {...})
  7. Mock generic collections using TypeReference

    master

    When mocking generic types like List<T>, Set<T>, or Map<K, V>, standard class references lose type information due to erasure. To mock these correctly, use JMockData.mock(new TypeReference<T>(){}).

    Note: You must include the empty curly braces {} in the TypeReference constructor to capture the generic type information.

    Examples:

    • Mocking a simple list: List<Integer>
    • Mocking a list of arrays: List<Integer[]>
    • Mocking a list of beans: List<BasicBean>
    • Mocking complex nested maps: Map<List<Map<Integer, String[][]>>, Map<Set<String>, Double[]>>
    // IMPORTANT: Use {} in TypeReference to capture generic types
    
    // Mocking basic types via TypeReference
    Integer integerNum = JMockData.mock(new TypeReference<Integer>(){});
    Integer[] integerArray = JMockData.mock(new TypeReference<Integer[]>(){});
    
    // Mocking collections
    List<Integer> integerList = JMockData.mock(new TypeReference<List<Integer>>(){});
    List<Integer[]> integerArrayList = JMockData.mock(new TypeReference<List<Integer[]>>(){});
    List<Integer>[] integerListArray = JMockData.mock(new TypeReference<List<Integer>[]>(){});
    
    // Mocking collections of entities
    List<BasicBean> basicBeanList = JMockData.mock(new TypeReference<List<BasicBean>>(){});
    
    // Mocking complex nested structures
    Map<List<Map<Integer, String[][]>>, Map<Set<String>, Double[]>> some = JMockData.mock(new TypeReference<Map<List<Map<Integer, String[][]>>, Map<Set<String>, Double[]>>>(){});
  8. Mock Java Beans (POJOs)

    master

    To mock a Java object (Bean), use JMockData.mock(YourClass.class).

    Best Practices & Behavior:

    • It is recommended to use plain beans.
    • The library uses reflection to assign values to properties.
    • It supports mocking properties inherited from parent classes.
    • It can handle complex nested structures including arrays, lists, sets, and maps within the bean.
    // Mocking a Java object
    BasicBean basicBean = JMockData.mock(BasicBean.class);
  9. Mock data using regular expressions

    master

    JMockData allows you to generate data based on regex patterns. Regex rules take precedence over other mocking rules.

    Supported Regex Syntax:

    • Character classes: \w, \W, \d, \D, \s, \S
    • Ranges: [0-9a-zA-Z], [abc123_]
    • Quantifiers: {n}, {n,}, {n,m}
    • Wildcards/Quantifiers: *, +, ., ?

    Unsupported Syntax:

    • (), ^, $, |, \n, \t, \cx, \b, \B, \f, etc.

    To apply regex to specific fields within a class, use .subConfig(Class<?> clazz, String fieldName).stringRegex("pattern") or .numberRegex("pattern").

    ```java
       /**
        * Mock data based on regex
        * Regex takes precedence over other rules
        */
       @Test
       public void testRegexMock() {
         MockConfig mockConfig = new MockConfig()
                     // Random paragraph string
                     .stringRegex("I'am a nice man\\.And I'll just scribble the characters, like:[a-z]{2}-[0-9]{2}-[abc123]{2}-\\w{2}-\\d{2}@\\s{1}-\\S{1}\\.?-\".")
                     // Email
                     .subConfig(RegexTestDataBean.class,"userEmail")
                     .stringRegex("[a-z0-9]{5,15}\\@\\w{3,5}\\.[a-z]{2,3}")
                     // Username rule
                     .subConfig(RegexTestDataBean.class,"userName")
                     .stringRegex("[a-zA-Z_]{1}[a-z0-9_]{5,15}")
                     // Age
                     .subConfig(RegexTestDataBean.class,"userAge")
                     .numberRegex("[1-9]{1}\\d?")
                     // User money
                     .subConfig(RegexTestDataBean.class,"userMoney")
                     .numberRegex("[1-9]{2}\\.\\d?")
                     // User score
                     .subConfig(RegexTestDataBean.class,"userScore")
                     .numberRegex("[1-9]{1}\\d{1}")
                     // User value
                     .subConfig(RegexTestDataBean.class,"userValue")
                     .numberRegex("[1-9]{1}\\d{3,8}")
                     .globalConfig();
       }
  10. Set decimal scale for numeric types

    master

    You can control the number of decimal places for BigDecimal, Double, and Float types using the decimalScale(int) method in MockConfig. The default scale is 2.

    ```java
     public void testDecimalScaleMock() {
        MockConfig mockConfig = new MockConfig()
                .doubleRange(-1.1d,9999.99999d)
                .floatRange(-1.11111f,9999.99999f)
                .decimalScale(3) // Sets decimal places to 3
                .globalConfig();
        JMockData.mock(BigDecimal.class, mockConfig);
      }
  11. Register custom Mocker classes

    master

    You can extend JMockData's capabilities by registering your own Mocker implementations for specific classes using the registerMocker method in MockConfig.

    MockConfig mockConfig = new MockConfig()
                .registerMocker(Mocker mocker, Class<T>... clazzs)