Skip to content

Snapmock is a snapshotting-mocking library for Java

License

Notifications You must be signed in to change notification settings

sickfar/snapmock

Repository files navigation

Overview

snapmock is a testing library for Java applications that captures method calls and their dependencies as snapshots, stored in JSON format. It helps automate unit testing and simplifies the creation of tests for methods with complex dependencies.

With snapmock, you can:

  • Verify method calls during unit testing by comparing them to saved snapshots.
  • Automatically generate test code based on snapshots, making it easier to create tests for methods with complex dependencies.

snapmock helps reduce boilerplate code in unit tests and improves test accuracy by automatically validating method call behavior against real invocations in your application.

Features

  • Capture method calls and dependencies in Spring Boot 3 applications using AOP.
  • Store method call snapshots as JSON files.
  • Automate Snapshot Testing: Verify method calls and dependencies against saved snapshots.
  • Generate Unit Tests: Generate unit tests from snapshots in multiple languages (Java only currently).

How to Capture Snapshots

To capture snapshots of method calls, you need to annotate the classes or methods you want to track with the @Snap annotation.

@Snap Annotation

  • On Methods: If you place @Snap on a method, only the calls to that specific method will be recorded.
  • On Classes: If you place @Snap on a class, all calls to the public methods of that class will be captured, including calls to any injected dependencies.
@Snap
public class MyService {
    public void someMethod() {
        // Method will be captured in the snapshot
    }

    public void anotherMethod() {
        // Method will also be captured in the snapshot
    }
}

Dependency Injection

snapmock supports capturing snapshots of dependencies that are injected via constructor injection or the @Autowired annotation.

@Component
public class MyService {
    
    private final MyDependency dependency;

    @Autowired
    public MyService(MyDependency dependency) {
        this.dependency = dependency;
    }

    @Snap
    public void someMethod() {
        // Snapshot of this method will include calls to `MyDependency` methods
        dependency.doSomething();
    }
}

@SnapDepFactory Annotation

If you are using dependency factories, mark the factory class or its injection point with the @SnapDepFactory annotation. This tells Snapmock to treat the factory as a special type of dependency.

@SnapDepFactory
@Component
public class MyFactory {
    public MyDependency createDependency() {
        return new MyDependency();
    }
}

This way, snapmock will correctly handle the creation and injection of dependencies from factories.

Example Snapshot

Here is an example of a snapshot JSON file generated by snapmock, capturing a method call and its dependencies:

{
  "main": {
    "className": "io.github.sickfar.snapmock.spring.simple.hello.HelloService",
    "methodName": "get",
    "parameterTypes": [],
    "arguments": [],
    "argumentTypes": null,
    "returnType": "io.github.sickfar.snapmock.spring.simple.app.HelloData",
    "result": {
      "data": "Hello World"
    },
    "exceptionType": null,
    "exceptionMessage": null
  },
  "dependencies": {
    "repository": "io.github.sickfar.snapmock.spring.simple.hello.HelloRepository"
  },
  "dependents": [
    {
      "className": "io.github.sickfar.snapmock.spring.simple.hello.HelloRepository",
      "methodName": "getMessage",
      "parameterTypes": [],
      "arguments": [],
      "argumentTypes": null,
      "returnType": "java.lang.String",
      "result": "Hello World",
      "exceptionType": null,
      "exceptionMessage": null
    }
  ],
  "factories": []
}

Limitations

  • Dependencies must be unique and must be injected via constructor or @Autowired. Configuration properties injection via @Value is not supported.
  • Currently, only Spring Boot 3 applications with AOP are supported.

Installation

You can include snapmock in your project by adding it as a dependency in your Maven or Gradle configuration.

Maven

<dependency>
  <groupId>io.github.sickfar.snapmock</groupId>
  <artifactId>snapmock</artifactId>
  <version>0.0.1</version>
</dependency>

Gradle

dependencies {
    implementation 'io.github.sickfar.snapmock:snapmock:0.0.1'
}

Usage

1. Automated Snapshot Testing

Once you've captured a snapshot of method calls, you can automatically test it by passing the snapshot JSON file to the doSnapshotTest method. The library will automatically verify that the recorded method calls match the current behavior.

@Test
void doSnapshotTest() {
    MockitoMockSupport.doSnapshotTest(new ClassPathResourceSource("/path/to/snapshot.json"));
}

2. Test Generation with snapmock-gen

The snapmock-gen tool generates unit tests based on the captured snapshots. It can output tests in multiple languages (Java only supported so far) and allows configuration of test and mock frameworks (JUnit and Mockito are supported so far).

Example Usage

To generate unit tests from a snapshot:

snapmock-gen -o ./generated-tests -l JAVA -tf junit -mf mockito -as hamcrest -m PER_SNAP_FILE /path/to/snapshot.json

This will:

  • Generate Java tests using JUnit, Mockito, and Hamcrest.
  • Save the generated test files to ./generated-tests.

Example of Generated Test Code

@ExtendWith(MockitoExtension.class)
class HelloServiceGetTest {
  @InjectMocks
  HelloService subject;

  @Mock
  HelloRepository helloRepository;

  @Test
  void testGet0() {
    final var source = new ClassPathResourceSource(HelloServiceGetTest.class, "HelloService_get_0.json");
    Mockito.doReturn(TestSupport.depResult(source, 0)).when(helloRepository).getMessage();
    final var result = subject.get();
    Assertions.assertEquals(TestSupport.subjResult(source), result);
  }
}

For more information about snapmock-gen, you can display help information for snapmock-gen by running:

snapmock-gen --help

License

snapmock is licensed under the MIT License.

Developed by Roman Aksenenko ([email protected])

About

Snapmock is a snapshotting-mocking library for Java

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages