Currently many tests share instances of ExportProvider for efficiency purposes. This mutable type ends up containing mutable objects, and sharing across tests can cause unexpected cross-test behavior changes.
The caching strategy can be improved by caching the IExportProviderFactory used to create the ExportProvider. This immutable object caches the expensive operations required to compose the MEF container, so the lightweight ExportProvider instances only need to invoke the constructors for contained types.
The overall approach in testing should achieve the following:
-
Rules for ExportProvider in testing
- During the execution of any given test, at most one
ExportProvider will be created
- An
ExportProvider created during a test must be disposed either within the test or as part of the teardown for the test
-
Rules for exported values in testing
-
An object normally obtained from the ExportProvider must only be obtained through the export provider. If a substitution object is required (e.g. a mock with specific behavior), the mock must be placed in the ExportProvider and then obtained from it. Constructors for MEF-exported types should have the following attribute on their constructor as a compile-time guarantee:
[Obsolete(
"This exported object must be obtained through the MEF export provider.",
error: true)]
-
Additional constraints
- Asynchronous (background) operations should be completed during the lifetime of each test, and joined to the test so failures are propagated to the test status. Each test should cancel unnecessary operations to avoid prolonging test runs.
Currently many tests share instances of
ExportProviderfor efficiency purposes. This mutable type ends up containing mutable objects, and sharing across tests can cause unexpected cross-test behavior changes.The caching strategy can be improved by caching the
IExportProviderFactoryused to create theExportProvider. This immutable object caches the expensive operations required to compose the MEF container, so the lightweightExportProviderinstances only need to invoke the constructors for contained types.The overall approach in testing should achieve the following:
Rules for
ExportProviderin testingExportProviderwill be createdExportProvidercreated during a test must be disposed either within the test or as part of the teardown for the testRules for exported values in testing
An object normally obtained from the
ExportProvidermust only be obtained through the export provider. If a substitution object is required (e.g. a mock with specific behavior), the mock must be placed in theExportProviderand then obtained from it. Constructors for MEF-exported types should have the following attribute on their constructor as a compile-time guarantee:Additional constraints