Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add supporting for sealed class and sealed interface #921

Merged
merged 1 commit into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/content/v1.0.x/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ menu:
docs:
weight: 100
---
sectionStart
### v.1.0.14
Add supporting for sealed class and sealed interface.

sectionEnd

sectionStart
### v.1.0.13
Add InterfacePlugin supports abstract classes through `abstractClassExtends` option.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ public final class FixtureMonkeyOptionsBuilder {
@Nullable
private Function<JavaConstraintGenerator, JavaTimeArbitraryGeneratorSet> generateJavaTimeArbitrarySet = null;
private InstantiatorProcessor instantiatorProcessor = new JavaInstantiatorProcessor();
private final JdkVariantOptions jdkVariantOptions = new JdkVariantOptions();

FixtureMonkeyOptionsBuilder() {
}
Expand Down Expand Up @@ -511,6 +512,8 @@ public FixtureMonkeyOptionsBuilder instantiatorProcessor(
}

public FixtureMonkeyOptions build() {
jdkVariantOptions.apply(this);

ObjectPropertyGenerator defaultObjectPropertyGenerator = defaultIfNull(
this.defaultObjectPropertyGenerator,
() -> FixtureMonkeyOptions.DEFAULT_OBJECT_PROPERTY_GENERATOR
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.fixturemonkey.api.option;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

@API(since = "1.0.14", status = Status.INTERNAL)
public final class JdkVariantOptions {
public void apply(FixtureMonkeyOptionsBuilder optionsBuilder){
// omitted because JDK8 is a default version
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.fixturemonkey.api.generator;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

import com.navercorp.fixturemonkey.api.property.Property;
import com.navercorp.fixturemonkey.api.property.PropertyUtils;
import com.navercorp.fixturemonkey.api.type.Types;

@API(since = "1.0.14", status = Status.EXPERIMENTAL)
public final class SealedTypeObjectPropertyGenerator implements ObjectPropertyGenerator {
@Override
public ObjectProperty generate(ObjectPropertyGeneratorContext context) {
Property sealedTypeProperty = context.getProperty();
Class<?> actualType = Types.getActualType(sealedTypeProperty.getType());
double nullInject = context.getNullInjectGenerator().generate(context);

Map<Property, List<Property>> childPropertiesByProperty = new HashMap<>();
for (Class<?> subClass : actualType.getPermittedSubclasses()) {
Property subProperty = PropertyUtils.toProperty(subClass);

List<Property> subPropertyChildProperties = context.getPropertyGenerator()
.generateChildProperties(subProperty);

childPropertiesByProperty.put(subProperty, subPropertyChildProperties);
}

return new ObjectProperty(
sealedTypeProperty,
context.getPropertyNameResolver(),
nullInject,
context.getElementIndex(),
childPropertiesByProperty
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.fixturemonkey.api.option;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

import com.navercorp.fixturemonkey.api.generator.ObjectPropertyGenerator;
import com.navercorp.fixturemonkey.api.generator.SealedTypeObjectPropertyGenerator;
import com.navercorp.fixturemonkey.api.type.Types;

@API(since = "1.0.14", status = Status.INTERNAL)
public final class JdkVariantOptions {
private static final ObjectPropertyGenerator SEALED_TYPE_OBJECT_PROPERTY_GENERATOR =
new SealedTypeObjectPropertyGenerator();

public void apply(FixtureMonkeyOptionsBuilder optionsBuilder) {
optionsBuilder.insertFirstArbitraryObjectPropertyGenerator(
p -> Types.getActualType(p.getType()).isSealed(),
SEALED_TYPE_OBJECT_PROPERTY_GENERATOR
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.fixturemonkey.tests.java17;

import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT;
import static org.assertj.core.api.BDDAssertions.then;

import java.beans.ConstructorProperties;

import org.junit.jupiter.api.RepeatedTest;

import com.navercorp.fixturemonkey.FixtureMonkey;
import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector;

class SealedClassTest {
private static final FixtureMonkey SUT = FixtureMonkey.builder()
.objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE)
.defaultNotNull(true)
.build();

private static sealed class SealedClass permits SealedClassImpl {
}

private static final class SealedClassImpl extends SealedClass {
private final String value;

@ConstructorProperties("value")
public SealedClassImpl(String value) {
this.value = value;
}

public String getValue() {
return value;
}
}

@RepeatedTest(TEST_COUNT)
void sampleSealedClass() {
// when
SealedClass actual = SUT.giveMeOne(SealedClass.class);

then(actual).isInstanceOf(SealedClassImpl.class);
}

private sealed interface SealedInterface permits SealedInterfaceImpl {
}

private record SealedInterfaceImpl(String value) implements SealedInterface {
}

@RepeatedTest(TEST_COUNT)
void sampleSealedInterface() {
// when
SealedInterface actual = SUT.giveMeOne(SealedInterface.class);

then(actual).isInstanceOf(SealedInterface.class);
}

private record SealedClassProperty(
SealedClass sealedClass,
SealedInterface sealedInterface
) {
}

@RepeatedTest(TEST_COUNT)
void sampleSealedClassProperty() {
// when
SealedClassProperty actual = SUT.giveMeOne(SealedClassProperty.class);

then(actual.sealedInterface()).isInstanceOf(SealedInterfaceImpl.class);
then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class);
}

@RepeatedTest(TEST_COUNT)
void fixedSealedClassProperty() {
// when
SealedClassProperty actual = SUT.giveMeBuilder(SealedClassProperty.class)
.fixed()
.sample();

then(actual.sealedInterface()).isInstanceOf(SealedInterfaceImpl.class);
then(actual.sealedClass()).isInstanceOf(SealedClassImpl.class);
}
}
Loading