Security News
Introducing the Socket Python SDK
The initial version of the Socket Python SDK is now on PyPI, enabling developers to more easily interact with the Socket REST API in Python projects.
com.github.nylle:javafixture
Advanced tools
JavaFixture is the attempt to bring Mark Seemann's AutoFixture for .NET to the Java world. Its purpose is to generate full object graphs for use in test suites with a fluent API for customising the test objects during generation.
JavaFixture is the attempt to bring the incredibly easy usage of Mark Seemann's AutoFixture for .NET to the Java world.
The purpose of this project is to generate full object graphs for use in test suites.
<dependency>
<groupId>com.github.nylle</groupId>
<artifactId>javafixture</artifactId>
<version>2.10.1</version>
<scope>test</scope>
</dependency>
Via constructor:
var fixture = new Fixture();
...or using a static factory method for convenience:
var fixture = Fixture.fixture();
String result = fixture.create(String.class);
String: "c3932f6f-59ae-43df-8ee9-8788474a3f87"
If a String
-field is annotated with @Size
or @Column
, those limits will be respected:
public class TestObjectWithJavaxValidationAnnotations {
@Size(min = 3, max = 6)
private String withMinMaxAnnotation;
@Column(length = 6)
private String withColumnLengthAnnotation;
}
int result = fixture.create(int.class);
int: -1612385443
ParentDto result = fixture.create(ParentDto.class);
List<String> result = fixture.createMany(String.class).collect(Collectors.toList());
ArrayList:
List<String> result = fixture.build(String.class).createMany(4).collect(Collectors.toList());
ArrayList:
List<String> result = new ArrayList<>();
result.add("HELLO!");
fixture.addManyTo(result, String.class);
ArrayList:
TestDto result = fixture.build(TestDto.class)
.with(x -> x.setMyPrivateField("HELLO!"))
.with(x -> x.myPublicField = 123)
.create();
TestDto:
TestDto result = fixture.build(TestDto.class)
.with("myPrivateField", "HELLO!")
.create();
TestDto:
ParentDto result = fixture.build(ParentDto.class)
.with(String.class, "hello")
.create();
TestDto result = fixture.build(TestDto.class)
.without("myPrivateField")
.without("myPublicField")
.create();
TestDto:
Primitives will receive their default-value, classes will be null
.
Due to Java's type erasure (further reading: baeldung), it is difficult to reflect generic classes on runtime and the following doesn't work:
fixture.create(Optional<String>.class); // does not compile
Using JavaFixture however it can be achieved through a little trick:
Optional<String> result = fixture.create(new SpecimenType<Optional<String>>(){});
Please note the empty curly braces ({}
) after the call to the constructor of SpecimenType
. These are necessary for generic reflection through an abstract superclass.
SpecimenType
can also be used for non-generic classes, but will lose any parametrisation for generic classes:
Optional result = fixture.create(SpecimenType.fromClass(Optional.class));
Optional result = fixture.create(Optional.class); // convenience method for above
There might be some cases when you want to create an object not by instantiating it and setting all fields, but by calling one of its constructors and feeding it random values.
var result = fixture.construct(new SpecimenType<MyGeneric<String>>(){});
var result = fixture.construct(String.class);
Keep in mind that only public constructors are allowed.
The values below are the default values, used when no configuration is provided.
var config = Configuration.configure()
.collectionSizeRange(2, 10)
.streamSize(3)
.usePositiveNumbersOnly(false)
.clock(Clock.fixed(Instant.now(), ZoneOffset.UTC));
var fixture = new Fixture(config);
The fixture can also be configured fluently inline:
var configuredFixture = Fixture.configuration()
.collectionSizeRange(2, 10)
.streamSize(3)
.usePositiveNumbersOnly(false)
.clock(Clock.fixed(Instant.now(), ZoneOffset.UTC))
.fixture();
collectionSizeRange
determines the range from which a random collection size will be picked when creating any collection, map or arraystreamSize
determines the number of objects to be returned when using Stream<T> Fixture.createMany(Class<T>)
usePositiveNumbersOnly
defines whether to generate only positive numbers including 0 for short
, int
, long
, float
, and double
clock
sets the clock to use when creating time-based valuesIn order to use JUnit5 support you need to add the following dependencies if not already present.
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
Remember to also include the vintage
dependency if you still have JUnit4-tests, otherwise they won't be run.
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
All arguments of the test-method below will be provided as a random object generated by JavaFixture.
@TestWithFixture
void injectParameterViaMethodExtension(TestDto testObject, int intValue, Optional<String> genericObject) {
assertThat(testObject).isInstanceOf(TestDto.class);
assertThat(intValue).isBetween(Integer.MIN_VALUE, Integer.MAX_VALUE);
assertThat(genericObject).isInstanceOf(Optional.class);
assertThat(genericObject).isPresent();
assertThat(genericObject.get()).isInstanceOf(String.class);
}
Additional annotated arguments are allowed:
@TestWithFixture
@DisplayName("Annotated parameters will work when they are at the end of the list")
void injectTempDirViaJunit(Integer intValue, @TempDir Path injectedTempDir) {
assertThat(injectedTempDir).isEqualTo(tempPath);
assertThat(intValue).isNotNull();
}
You can also configure Fixture inline:
@TestWithFixture(minCollectionSize = 11, maxCollectionSize = 11, positiveNumbersOnly = true)
void configurableFixture(List<Integer> input) {
assertThat(input).hasSize(11);
assertThat(input).allMatch(x -> x > 1);
}
For some syntactic sugar, this library comes with a wrapper for JUnit5's parameterized
test feature, called @TestWithCases
.
@TestWithCases
@TestCase(str1 = "", int2 = 0)
@TestCase(str1 = " ", int2 = 1)
@TestCase(str1 = "foo", int2 = 3)
@TestCase(str1 = "hello", int2 = 5)
void testStringLength(String input, int expected) {
assertThat(input.length()).isEqualTo(expected);
}
The test will be run for every @TestCase
-annotation injecting the provided values into the test's arguments.
Due to Java's limited annotation design, the following rules apply:
String
, Class
or primitive like int
, boolean
, float
,
etc.str1 = "foo"
can only be applied to the first argument which must be of type
String
, while int2 = 3
can only be applied to the second argument which obviously must
be of type int
and so on.If you are using @TestWithFixture
and want to make the test parameterized, you can do so by using the annotation @Fixture
inline:
@TestWithCases
@TestCase(str1 = "foo")
@TestCase(str1 = "bar")
void testStringLength(String input, @Fixture TestDto fixture) {
assertThat(input).hasSize(3);
assertThat(fixture).isNotNull();
}
The test will be run for every @TestCase
-annotation injecting the provided and the randomly generated values into the test's arguments.
The random values will be identical for all test-cases!
Since version 2.10.0, a new experimental feature is available. If you enable experimentalInterfaces
, Fixture will attempt to find implementations for an interface (or non-abstract subclasses of an abstract class) on your classpath and create those instead of wrapping the interface with a proxy. If no suitable implementation is found, the proxy will be created as a fallback.
@Test
void canCreateGenericObjectFromInterfaceWithMismatchingNumberOfTypeParameters() {
var fixture = new Fixture(Configuration.configure().experimentalInterfaces(true));
var result = fixture.create(new SpecimenType<GenericInterfaceTUWithGenericImplementationU<String, Integer>>() {});
assertThat(result).isInstanceOf(GenericInterfaceTUWithGenericImplementationUImpl.class);
assertThat(result.publicField).isInstanceOf(Integer.class);
assertThat(result.getT()).isInstanceOf(String.class);
assertThat(result.getU()).isInstanceOf(Integer.class);
}
This setting is not supported with annotations. However, to enable this feature globally, place a file javafixture/com.github.nylle.javafixture.experimetalInterfaces
on your classpath with the content "enabled". To disable it, either delete the file or change the content to something else, e.g. "disabled".
FAQs
JavaFixture is the attempt to bring Mark Seemann's AutoFixture for .NET to the Java world. Its purpose is to generate full object graphs for use in test suites with a fluent API for customising the test objects during generation.
We found that com.github.nylle:javafixture demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The initial version of the Socket Python SDK is now on PyPI, enabling developers to more easily interact with the Socket REST API in Python projects.
Security News
Floating dependency ranges in npm can introduce instability and security risks into your project by allowing unverified or incompatible versions to be installed automatically, leading to unpredictable behavior and potential conflicts.
Security News
A new Rust RFC proposes "Trusted Publishing" for Crates.io, introducing short-lived access tokens via OIDC to improve security and reduce risks associated with long-lived API tokens.