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.
- 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).
To capture snapshots of method calls, you need to annotate the classes or methods you want to track with the @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
}
}
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();
}
}
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.
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": []
}
- 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.
You can include snapmock in your project by adding it as a dependency in your Maven or Gradle configuration.
<dependency>
<groupId>io.github.sickfar.snapmock</groupId>
<artifactId>snapmock</artifactId>
<version>0.0.1</version>
</dependency>
dependencies {
implementation 'io.github.sickfar.snapmock:snapmock:0.0.1'
}
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"));
}
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).
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.
@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
snapmock is licensed under the MIT License.
Developed by Roman Aksenenko ([email protected])