Skip to content

Commit cedaab3

Browse files
committed
feat(fixtures): add support for DatasetType in DatasetRecipe and its integration across fixture builders and tests using a new recipe
1 parent 2636065 commit cedaab3

6 files changed

Lines changed: 129 additions & 13 deletions

File tree

src/test/java/edu/harvard/iq/dataverse/util/testing/fixtures/DatasetFixture.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import edu.harvard.iq.dataverse.Dataset;
66
import edu.harvard.iq.dataverse.DatasetVersion;
77
import edu.harvard.iq.dataverse.FileMetadata;
8+
import edu.harvard.iq.dataverse.dataset.DatasetType;
89
import edu.harvard.iq.dataverse.datavariable.DataVariable;
910
import edu.harvard.iq.dataverse.datavariable.VarGroup;
1011
import edu.harvard.iq.dataverse.datavariable.VariableMetadata;
@@ -33,6 +34,7 @@
3334
*/
3435
public record DatasetFixture(
3536
Dataset dataset,
37+
DatasetType datasetType,
3638
DatasetVersion currentVersion,
3739
List<FileMetadata> fileMetadatas,
3840
List<DataFile> dataFiles,

src/test/java/edu/harvard/iq/dataverse/util/testing/fixtures/DatasetFixtureBuilder.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import edu.harvard.iq.dataverse.Dataset;
66
import edu.harvard.iq.dataverse.DatasetVersion;
77
import edu.harvard.iq.dataverse.FileMetadata;
8+
import edu.harvard.iq.dataverse.dataset.DatasetType;
89
import edu.harvard.iq.dataverse.datavariable.DataVariable;
910
import edu.harvard.iq.dataverse.datavariable.VarGroup;
1011
import edu.harvard.iq.dataverse.datavariable.VariableMetadata;
@@ -114,6 +115,7 @@ public DatasetFixture build() {
114115

115116
// Create the top-level dataset and its current version, then wire them.
116117
Dataset dataset = createEmptyDataset(context);
118+
DatasetType datasetType = datasetRecipe.datasetTypeRecipe().datasetType();
117119
DatasetVersion currentVersion = createDatasetVersion(context);
118120
wireDatasetAndVersion(dataset, currentVersion);
119121

@@ -123,7 +125,7 @@ public DatasetFixture build() {
123125
// Walk the file recipes and create files (plus tabular structure where applicable).
124126
buildVersionFiles(currentVersion, context, accumulator);
125127

126-
return accumulator.toFixture(dataset, currentVersion);
128+
return accumulator.toFixture(dataset, datasetType, currentVersion);
127129
}
128130

129131
/**
@@ -138,6 +140,10 @@ public DatasetFixture build() {
138140
private Dataset createEmptyDataset(BuildContext context) {
139141
Dataset dataset = new Dataset();
140142
populator.populateDataset(dataset, context);
143+
// DatasetType comes from the recipe, not the populator, because it is a shared
144+
// reference entity that must pre-exist in the database. The recipe either wraps
145+
// // a pre-existing instance or builds one from scalar values for this fixture.
146+
dataset.setDatasetType(datasetRecipe.datasetTypeRecipe().datasetType());
141147
dataset.setVersions(new ArrayList<>());
142148
return dataset;
143149
}
@@ -481,9 +487,10 @@ void addVariableMetadata(VariableMetadata metadata) {
481487
variableMetadata.add(metadata);
482488
}
483489

484-
DatasetFixture toFixture(Dataset dataset, DatasetVersion currentVersion) {
490+
DatasetFixture toFixture(Dataset dataset, DatasetType datasetType, DatasetVersion currentVersion) {
485491
return new DatasetFixture(
486492
dataset,
493+
datasetType,
487494
currentVersion,
488495
fileMetadatas,
489496
dataFiles,

src/test/java/edu/harvard/iq/dataverse/util/testing/fixtures/DatasetFixtureTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import edu.harvard.iq.dataverse.settings.JvmSettings;
77
import edu.harvard.iq.dataverse.util.json.JsonPrinter;
88
import edu.harvard.iq.dataverse.util.testing.recipes.DatasetRecipe;
9+
import edu.harvard.iq.dataverse.util.testing.recipes.DatasetTypeRecipe;
910
import edu.harvard.iq.dataverse.util.testing.recipes.FileRecipe;
1011
import edu.harvard.iq.dataverse.util.testing.recipes.VariableSetRecipe;
1112
import edu.harvard.iq.dataverse.util.testing.recipes.VersionRecipe;
@@ -38,6 +39,7 @@ static void tearDown() {
3839
void smoketest() {
3940

4041
var recipe = DatasetRecipe.of(
42+
DatasetTypeRecipe.dataset(),
4143
VersionRecipe.of(
4244
FileRecipe.tabular(10, VariableSetRecipe.uniform(10)),
4345
//FileRecipe.tabular(50, VariableSetRecipe.byPredicate()),

src/test/java/edu/harvard/iq/dataverse/util/testing/fixtures/MinimalPopulator.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import edu.harvard.iq.dataverse.DatasetVersion;
77
import edu.harvard.iq.dataverse.FileMetadata;
88
import edu.harvard.iq.dataverse.TermsOfUseAndAccess;
9-
import edu.harvard.iq.dataverse.dataset.DatasetType;
109
import edu.harvard.iq.dataverse.datavariable.DataVariable;
1110
import edu.harvard.iq.dataverse.datavariable.VarGroup;
1211
import edu.harvard.iq.dataverse.datavariable.VariableMetadata;
@@ -31,7 +30,6 @@ public void populateDataset(Dataset dataset, BuildContext context) {
3130
dataset.setAuthority("10.5072");
3231
dataset.setIdentifier("fixture-dataset-" + context.sequence());
3332
dataset.setStorageIdentifier("fixture-storage-" + context.sequence());
34-
dataset.setDatasetType(new DatasetType());
3533

3634
// necessary as DvObject says "not nullable"
3735
dataset.setCreateDate(context.getTimestamp());
Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package edu.harvard.iq.dataverse.util.testing.recipes;
22

3+
import java.util.Objects;
4+
35
/**
46
* Top-level recipe describing how to construct a {@code Dataset} fixture.
57
*
@@ -13,31 +15,43 @@
1315
* to evolve later.</p>
1416
*/
1517
public interface DatasetRecipe {
16-
18+
19+
/**
20+
* Returns the dataset type recipe providing the type to assign.
21+
*
22+
* @return dataset type recipe
23+
*/
24+
DatasetTypeRecipe datasetTypeRecipe();
25+
1726
/**
1827
* Returns the recipe describing the current version of the dataset.
1928
*
2029
* @return recipe for the current dataset version
2130
*/
2231
VersionRecipe currentVersionRecipe();
23-
32+
2433
/**
25-
* Creates a dataset recipe with a single current version recipe.
34+
* Creates a dataset recipe with the supplied type and version recipes.
2635
*
27-
* @param currentVersionRecipe the recipe for the current dataset version
36+
* @param datasetTypeRecipe recipe providing the dataset type
37+
* @param currentVersionRecipe recipe for the current dataset version
2838
* @return a dataset recipe
2939
*/
30-
static DatasetRecipe of(VersionRecipe currentVersionRecipe) {
31-
return new SimpleDatasetRecipe(currentVersionRecipe);
40+
static DatasetRecipe of(DatasetTypeRecipe datasetTypeRecipe, VersionRecipe currentVersionRecipe) {
41+
Objects.requireNonNull(datasetTypeRecipe, "datasetTypeRecipe must not be null");
42+
Objects.requireNonNull(currentVersionRecipe, "currentVersionRecipe must not be null");
43+
return new SimpleDatasetRecipe(datasetTypeRecipe, currentVersionRecipe);
3244
}
33-
45+
3446
/**
3547
* Minimal immutable implementation of {@link DatasetRecipe}.
3648
*
37-
* @param currentVersionRecipe the recipe for the current dataset version
49+
* @param datasetTypeRecipe recipe providing the dataset type
50+
* @param currentVersionRecipe recipe for the current dataset version
3851
*/
3952
record SimpleDatasetRecipe(
40-
VersionRecipe currentVersionRecipe
53+
DatasetTypeRecipe datasetTypeRecipe,
54+
VersionRecipe currentVersionRecipe
4155
) implements DatasetRecipe {
4256
}
4357
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package edu.harvard.iq.dataverse.util.testing.recipes;
2+
3+
import edu.harvard.iq.dataverse.dataset.DatasetType;
4+
5+
/**
6+
* Recipe providing the {@link DatasetType} to assign to a generated dataset fixture.
7+
*
8+
* <p>Unlike structural recipes such as {@link VersionRecipe} or {@link FileRecipe},
9+
* this is not a construction recipe. It is a reference/creation provider — the
10+
* dataset type it produces is expected to be persisted before the dataset fixture
11+
* is committed to the database.</p>
12+
*
13+
* <p>Two factory styles are available:</p>
14+
* <ul>
15+
* <li>{@link #of(String, String, String)} — fluent factory that creates a new
16+
* {@link DatasetType} from scalar values. Use this when generating a single
17+
* dataset fixture and you want a self-contained recipe.</li>
18+
* <li>{@link #of(DatasetType)} — wraps a pre-existing instance. Use this when
19+
* you want to share the same type across multiple dataset recipes, or when
20+
* the type has already been persisted elsewhere.</li>
21+
* </ul>
22+
*/
23+
public interface DatasetTypeRecipe {
24+
25+
/**
26+
* Returns the dataset type to assign to the generated dataset.
27+
*
28+
* <p>The returned instance may be newly created or pre-existing, depending on
29+
* the implementation. Either way, it must be persisted before the dataset
30+
* fixture is committed to the database.</p>
31+
*
32+
* @return dataset type instance
33+
*/
34+
DatasetType datasetType();
35+
36+
/**
37+
* Creates a recipe that builds a new {@link DatasetType} from the supplied
38+
* scalar values.
39+
*
40+
* <p>This is the preferred factory for single-dataset fixture scenarios where
41+
* the type does not need to be reused or pre-built externally. The resulting
42+
* type will need to be persisted before the dataset is committed.</p>
43+
*
44+
* @param name machine-readable name used in APIs and stored in the database
45+
* @param displayName human-readable name shown in the UI
46+
* @param description optional description of the dataset type
47+
* @return a dataset type recipe producing a new type from the supplied values
48+
*/
49+
static DatasetTypeRecipe of(String name, String displayName, String description) {
50+
DatasetType datasetType = new DatasetType();
51+
datasetType.setName(name);
52+
datasetType.setDisplayName(displayName);
53+
datasetType.setDescription(description);
54+
return new FixedDatasetTypeRecipe(datasetType);
55+
}
56+
57+
/**
58+
* Creates a recipe that wraps a pre-existing {@link DatasetType} instance.
59+
*
60+
* <p>Use this when the type has already been persisted, or when you want to
61+
* share the same type instance across multiple dataset recipes.</p>
62+
*
63+
* @param datasetType pre-existing dataset type to use
64+
* @return a dataset type recipe wrapping the supplied instance
65+
*/
66+
static DatasetTypeRecipe of(DatasetType datasetType) {
67+
return new FixedDatasetTypeRecipe(datasetType);
68+
}
69+
70+
/**
71+
* Creates a recipe using the standard {@value DatasetType#DATASET_TYPE_DATASET}
72+
* dataset type with sensible display defaults.
73+
*
74+
* <p>This is a convenience shortcut for the most common fixture scenario,
75+
* where you just need a valid persisted type and do not care about specific
76+
* type semantics.</p>
77+
*
78+
* @return a dataset type recipe for the default dataset type
79+
*/
80+
static DatasetTypeRecipe dataset() {
81+
return of(DatasetType.DATASET_TYPE_DATASET, "Dataset", "Standard dataset type for fixtures");
82+
}
83+
84+
/**
85+
* Minimal immutable recipe holding a fixed dataset type instance.
86+
*
87+
* @param datasetType dataset type to return
88+
*/
89+
record FixedDatasetTypeRecipe(
90+
DatasetType datasetType
91+
) implements DatasetTypeRecipe {
92+
}
93+
}

0 commit comments

Comments
 (0)