Skip to content

Commit f4699de

Browse files
authored
Add test of deterministic and non deterministic provider's methods (#743)
1 parent d1992a1 commit f4699de

File tree

7 files changed

+98
-40
lines changed

7 files changed

+98
-40
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package net.datafaker.annotations;
2+
3+
4+
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Retention;
6+
import java.lang.annotation.RetentionPolicy;
7+
import java.lang.annotation.Target;
8+
9+
@Retention(RetentionPolicy.RUNTIME)
10+
@Target(ElementType.METHOD)
11+
public @interface Deterministic {
12+
}

src/main/java/net/datafaker/providers/base/Address.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.datafaker.providers.base;
22

3+
import net.datafaker.annotations.Deterministic;
4+
35
/**
46
* @since 0.8.0
57
*/
@@ -67,6 +69,7 @@ public String streetSuffix() {
6769
return resolve("address.street_suffix");
6870
}
6971

72+
@Deterministic
7073
public String streetPrefix() {
7174
return resolve("address.street_prefix");
7275
}

src/main/java/net/datafaker/providers/base/Drone.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.datafaker.providers.base;
22

3+
import net.datafaker.annotations.Deterministic;
4+
35
/**
46
* An unmanned aerial vehicle (UAV), commonly known as a drone, is an aircraft without any human pilot, crew, or passengers on board.
57
*
@@ -107,6 +109,7 @@ public String minShutterSpeed() {
107109
return resolve("drone.min_shutter_speed");
108110
}
109111

112+
@Deterministic
110113
public String shutterSpeedUnits() {
111114
return resolve("drone.shutter_speed_units");
112115
}

src/main/java/net/datafaker/providers/base/Locality.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.datafaker.providers.base;
22

3+
import net.datafaker.annotations.Deterministic;
4+
35
import java.io.File;
46
import java.io.IOException;
57
import java.lang.management.ManagementFactory;
@@ -42,6 +44,7 @@ public Locality(BaseProviders baseProviders) {
4244
*
4345
* @return a List of Strings with the name of the locale (eg. "es", "es-MX")
4446
*/
47+
@Deterministic
4548
public List<String> allSupportedLocales() {
4649
return allSupportedLocales(Set.of("datafaker"));
4750
}

src/main/java/net/datafaker/providers/base/Mbti.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,43 @@
11
package net.datafaker.providers.base;
22

3+
import java.util.function.Supplier;
4+
35
/**
46
* Myers-Briggs Type Indicator
57
*
68
* @since 1.5.0
79
*/
810
public class Mbti extends AbstractProvider<BaseProviders> {
911

10-
private final String choice;
12+
private final Supplier<String> choice;
1113

1214
public Mbti(final BaseProviders faker) {
1315
super(faker);
14-
this.choice = this.faker.resolve("mbti.choice");
16+
this.choice = () -> this.faker.resolve("mbti.choice");
1517
}
1618

1719
public String type() {
18-
return resolve("mbti.".concat(choice).concat(".type"));
20+
return resolve("mbti.".concat(choice.get()).concat(".type"));
1921
}
2022

2123
public String name() {
22-
return resolve("mbti.".concat(choice).concat(".name"));
24+
return resolve("mbti.".concat(choice.get()).concat(".name"));
2325
}
2426

2527
public String characteristic() {
26-
return resolve("mbti.".concat(choice).concat(".characteristic"));
28+
return resolve("mbti.".concat(choice.get()).concat(".characteristic"));
2729
}
2830

2931
public String personage() {
30-
return resolve("mbti.".concat(choice).concat(".personage"));
32+
return resolve("mbti.".concat(choice.get()).concat(".personage"));
3133
}
3234

3335
public String merit() {
34-
return resolve("mbti.".concat(choice).concat(".merit"));
36+
return resolve("mbti.".concat(choice.get()).concat(".merit"));
3537
}
3638

3739
public String weakness() {
38-
return resolve("mbti.".concat(choice).concat(".weakness"));
40+
return resolve("mbti.".concat(choice.get()).concat(".weakness"));
3941
}
4042

4143

src/test/java/net/datafaker/FakerTest.java

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
package net.datafaker;
22

3+
import net.datafaker.annotations.Deterministic;
4+
import net.datafaker.providers.base.AbstractProvider;
35
import net.datafaker.providers.base.BaseFaker;
46
import org.junit.jupiter.api.RepeatedTest;
57
import org.junit.jupiter.api.Test;
68
import org.junit.jupiter.params.ParameterizedTest;
79
import org.junit.jupiter.params.provider.ValueSource;
8-
10+
import org.reflections.Reflections;
11+
12+
import java.lang.reflect.Constructor;
13+
import java.lang.reflect.InvocationTargetException;
14+
import java.lang.reflect.Method;
15+
import java.lang.reflect.Modifier;
16+
import java.util.Arrays;
17+
import java.util.Collection;
18+
import java.util.HashSet;
919
import java.util.Locale;
1020
import java.util.Map;
1121
import java.util.Random;
22+
import java.util.Set;
1223
import java.util.concurrent.Callable;
24+
import java.util.stream.Collectors;
1325

1426
import static org.assertj.core.api.Assertions.assertThat;
1527
import static org.assertj.core.api.Assertions.assertThatThrownBy;
28+
import static org.reflections.scanners.Scanners.SubTypes;
1629

1730
class FakerTest extends AbstractFakerTest {
1831

@@ -348,4 +361,57 @@ void shouldNotApplyCachingToMethodsWithParameters() {
348361
String flight2 = faker.expression("#{Aviation.flight 'ICAO'}");
349362
assertThat(flight2).matches("[A-z]{3}\\d{1,4}");
350363
}
364+
365+
@Test
366+
void testDeterministicAndNonDeterministicProvidersReturnValues() {
367+
final Reflections reflections = new Reflections("net.datafaker.providers");
368+
Set<Class<?>> classes = reflections.get(SubTypes.of(AbstractProvider.class).asClass());
369+
for (var clazz: classes) {
370+
Collection<Method> methods = Arrays.stream(clazz.getDeclaredMethods())
371+
.filter(m -> Modifier.isPublic(m.getModifiers()) && m.getParameterCount() == 0).collect(Collectors.toSet());
372+
if (methods.isEmpty()) continue;
373+
Constructor<AbstractProvider<?>> constructor = null;
374+
final AbstractProvider<?> ap;
375+
try {
376+
Set<Constructor<AbstractProvider<?>>> constructorsWith1Arg =
377+
Arrays.stream(clazz.getDeclaredConstructors())
378+
.filter(c -> c.getParameterCount() == 1).map(c -> (Constructor<AbstractProvider<?>>) c)
379+
.collect(Collectors.toSet());
380+
for (var c: constructorsWith1Arg) {
381+
Class<?>[] types = c.getParameterTypes();
382+
if (types[0].isAssignableFrom(Faker.class)) {
383+
constructor = c;
384+
break;
385+
}
386+
}
387+
assertThat(constructor).isNotNull();
388+
constructor.setAccessible(true);
389+
ap = constructor.newInstance(faker);
390+
} catch (InvocationTargetException | InstantiationException |
391+
IllegalAccessException e) {
392+
throw new RuntimeException(e);
393+
}
394+
for (Method m: methods) {
395+
var set = new HashSet<>();
396+
try {
397+
for (int i = 0; i < 10; i++) {
398+
set.add(m.invoke(ap));
399+
}
400+
} catch (IllegalAccessException | InvocationTargetException e) {
401+
throw new RuntimeException(e);
402+
}
403+
if (m.isAnnotationPresent(Deterministic.class)) {
404+
assertThat(set)
405+
.as("Class: " + ap.getClass().getName()
406+
+ ", method: " + m.getName() + " should have the same return value")
407+
.hasSize(1);
408+
} else {
409+
assertThat(set)
410+
.as("Class: " + ap.getClass().getName()
411+
+ ", method: " + m.getName() + " should generate different return values")
412+
.hasSizeGreaterThan(1);
413+
}
414+
}
415+
}
416+
}
351417
}
Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
package net.datafaker.providers.entertainment;
22

33
import org.junit.jupiter.api.RepeatedTest;
4-
import org.junit.jupiter.params.ParameterizedTest;
5-
import org.junit.jupiter.params.provider.MethodSource;
64

7-
import java.util.Collection;
8-
import java.util.List;
9-
import java.util.function.Function;
10-
import java.util.stream.Collectors;
11-
import java.util.stream.Stream;
125

136
import static org.assertj.core.api.Assertions.assertThat;
147
import static org.assertj.core.util.Strings.isNullOrEmpty;
@@ -42,28 +35,4 @@ void releaseDate() {
4235
assertThat(oscarMovie.releaseDate()).matches("[A-Za-z,0-9 ]+");
4336
}
4437

45-
/**
46-
* Test for <a href="https://github.com/datafaker-net/datafaker/issues/741">issue741</a>
47-
*/
48-
@ParameterizedTest
49-
@MethodSource("argsProvider")
50-
void issue741(Function<OscarMovie, String> f) {
51-
final OscarMovie oscarMovie = faker.oscarMovie();
52-
assertThat(
53-
faker.stream(() -> f.apply(oscarMovie)).len(10).build()
54-
.<Stream<?>>get().collect(Collectors.toSet()))
55-
.hasSizeGreaterThan(1);
56-
}
57-
58-
static Collection<Function<OscarMovie, String>> argsProvider() {
59-
return List.of(
60-
OscarMovie::actor,
61-
OscarMovie::character,
62-
OscarMovie::getChoice,
63-
OscarMovie::getYear,
64-
OscarMovie::movieName,
65-
OscarMovie::quote,
66-
OscarMovie::releaseDate
67-
);
68-
}
6938
}

0 commit comments

Comments
 (0)