Question

I am attempting to use the shared part creation policy for a MEF export. It does not, however, seem to work the way I was thinking. I do the composition twice in my application and each time get a fresh copy of the object. I've proved this by adding an instance counter to the object instanciation

    static int instCount = 0;

    public FakeAutocompleteRepository()
    {
        instCount++;
        ...
    }

and running it all in debug. Indeed the second time I do a composition I get a new copy of the FakeAutocompleteRepository with instCount = 2. The export section contains

[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(IAutocompleteRepository))]
[ExportMetadata("IsTesting", "True")]
class FakeAutocompleteRepository : IAutocompleteRepository
{ ... }

Is there some trick to getting the same instance for subsiquent requests? In case it is something I'm doing during the composition this is how I'm doing that

var catalog = new AggregateCatalog();
                catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
                catalog.Catalogs.Add(new DirectoryCatalog("."));
                var container = new CompositionContainer(catalog);
                var batch = new CompositionBatch();
                batch.AddPart(this);
                container.Compose(batch);


                if (null != ConfigurationSettings.AppSettings["IsTesting"] && bool.Parse(ConfigurationSettings.AppSettings["IsTesting"]))
                    repository = container.GetExports<IAutocompleteRepository>().Where(expDef => expDef.Metadata.Keys.Contains("IsTesting")).Single().GetExportedObject();

Basically I'm trying to force a specific composition during testing. If you have a better idea for unit testing these compositions then I'm all ears.

Was it helpful?

Solution

I don't see anything specifically in your code that would cause more than one of your part to be created. Are you creating a different container for each composition? If you are, that is why you are getting separate instances.

As far as how to combine composition and unit testing in general, there is some discussion of this here.

OTHER TIPS

What I did for unit testing was avoid composition. For instance (I'm using WPF and MVVM here), let's say you want to test this ViewModel:

[Export("/MyViewModel")]
public class MyViewModel
{
    [ImportingConstructor]
    public MyViewModel(
        [Import("/Services/LoggingService")] ILoggingService l)
    {
        logger = l;
    }

    private ILoggingService logger { get; set; }

    /* ... */
}

I don't want to instantiate the full-blown logging service every time I do a unit test, so I have a MockLoggingService class that implements ILoggingService and it just swallows all the log messages, (or checks that the proper messages are being generated, if you care). Then I can do this in my unit test:

MyViewModel target = new MyViewModel(new MockLoggingService());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top