Hi there 👋 First off, thanks for the great package!
Note: The below context is maybe helpful but not necessary for the overall question. The TLDR question is at the very bottom of this issue.
I have a generator whose purpose is to act on annotated export and function Elements and create fakes of the Type passed into the annotation. It's not too dissimilar to the mockito package.
where GHomeData is a type that needs its fake generated. For most of that work, I use a *.data.gql.dart file (generated by ferry), but in some cases there are "special" types whose factories can not be derived simply using the above file. For those, the consumer of my Builder provides a file name (e.g special_type.dart) that is looked up using findAssets on BuildStep. This works at runtime but tests use MockBuildStep which breaks when anything is called on it. To work around this, I've implemented a wrapper generator that injects a FakeBuildStep that implements select functions (specific to my needs). That looks like this:
// in a test
class GeneratorWithFakeBuildStep extends GeneratorForAnnotation<GenerateGraphqlFakes> {
final FactoryGeneratorConfig config;
final String customTypesDirectory;
GeneratorWithFakeBuildStep({
required this.config,
required this.customTypesDirectory,
});
@override
Future<String> generateForAnnotatedElement(
Element element,
ConstantReader annotation,
BuildStep buildStep,
) {
final generator = FactoryGenerator(config);
return generator.generateForAnnotatedElement(
element,
annotation,
FakeBuildStep(customTypesDirectory),
);
}
}
FakeBuildStep itself does something similar to what is done when initializing a test LibraryReader:
// fake_build_step.dart
// ignore: subtype_of_sealed_class
class FakeBuildStep extends BuildStep {
final String testDirectory;
late final Map<String, String> assets;
FakeBuildStep(this.testDirectory) {
final map = Map.fromEntries(
Directory(testDirectory)
.listSync(recursive: true)
.whereType<File>()
.map((f) => MapEntry(f.path, f.readAsStringSync())),
);
String assetIdForFile(String fileName) => '$testPackageName|lib/$fileName';
assets = map.map((file, content) => MapEntry(assetIdForFile(file), content));
}
...
}
So, my primary question is: Is there a reason (other than simplicity) that MockBuildStep was used as the stand-in for the runtime BuildStep? If not, is there any interest in building out a more robust fake that would allow consumers to not need to use a workaround like the above? Or better yet, am I just doing something wrong?
Hi there 👋 First off, thanks for the great package!
Note: The below context is maybe helpful but not necessary for the overall question. The TLDR question is at the very bottom of this issue.
I have a generator whose purpose is to act on annotated export and function
Element
s and create fakes of theType
passed into the annotation. It's not too dissimilar to themockito
package.The usage of the annotation looks like:
where
GHomeData
is a type that needs its fake generated. For most of that work, I use a*.data.gql.dart
file (generated byferry
), but in some cases there are "special" types whose factories can not be derived simply using the above file. For those, the consumer of myBuilder
provides a file name (e.gspecial_type.dart
) that is looked up usingfindAssets
onBuildStep
. This works at runtime but tests useMockBuildStep
which breaks when anything is called on it. To work around this, I've implemented a wrapper generator that injects aFakeBuildStep
that implements select functions (specific to my needs). That looks like this:// in a test
FakeBuildStep
itself does something similar to what is done when initializing a testLibraryReader
:// fake_build_step.dart
My implementation of
findAssets
is as follows:So, my primary question is: Is there a reason (other than simplicity) that
MockBuildStep
was used as the stand-in for the runtimeBuildStep
? If not, is there any interest in building out a more robust fake that would allow consumers to not need to use a workaround like the above? Or better yet, am I just doing something wrong?