MEF and Unit Testing with NUnit

A few weeks ago I jumped on MEND (ComponentModel), and now I use it for a lot of my plugins, as well as for shared libraries. All in all, it was wonderful aside from the frequent errors on my part, which led to frustrating debugging sessions.

In any case, my application works fine, but my code changes related to MEF led to the failure of my automatic builds. Most of my unit tests were unsuccessful simply because the modules I tested depended on other modules that MEF had to load. I worked on these situations, bypassing MEF and directly creating these objects.

In other words, through MEF I will have something like

[Import] public ICandyInterface ci { get; set; } 

and

 [Export(typeof(ICandyInterface))] public class MyCandy : ICandyInterface { [ImportingConstructor] public MyCandy( [Import("name_param")] string name) {} ... } 

But in my unit tests, I would just use

 CandyInterface MyCandy = new CandyInterface( "Godiva"); 

In addition, CandyInterface requires a connection to the database I was working with, simply adding a test database to my unit test folder, and I have NUnit for all tests.

So here are my questions regarding this situation:

  • Is this a bad way to do something?
  • You recommend composing parts in [SetUp]
  • I have not yet learned how to use mocks in unit testing - is this a good example of the case when I could mock a basic database connection (somehow) just to return dummy data and not require a database?
  • If you have encountered something similar before, can you offer your experience and how you solved your problem? (or should it go into the wiki community?)
+4
source share
3 answers

You seem to be on the right track. A unit test should test unit , and this is what you do when you instantiate directly. If you let MEF create instances for you, they will aim for integration tests . Not that there is something wrong with the integration tests, but unit tests are usually more convenient to maintain, because you test each block separately.

You do not need a container for connecting instances in unit tests .

I usually recommend not creating layouts in SetUp, as this leads to General Fixture anti-pattern.

It is best to replace Test Doubles dependencies. Dynamic bullying is one of the most universal ways to do this, so definitely you need to learn.

+10
source

I agree that creating a DOC manually is much better than using a container of MEF composition to satisfy imports, but due to the fact that the note β€œlayout of fixtures during installation leads to a common pattern”, I want to mention that this is not always the case.

If you use a static container and satisfy import through CompositionInitializer.SatisfyImports you will have to deal with a common reinforcement pattern like CompositionInitializer.Initialize cannot be called more than once. However, you can always create a CompositionContainer, add directories, and call SatisyImportOnce on the container itself. In this case, you can use the new CompositionContainer in each test and get away with bypassing the common / common attribute

0
source

I blogged on how to perform unit tests (not nunit, but works the same) with MEF. The trick was to use MockExportProvider, and I created a test base for all my tests to inherit.

This is my main AutoWire feature that works for integration and unit tests:

 protected void AutoWire(MockExportProvider mocksProvider, params Assembly[] assemblies){ CompositionContainer container = null; var assCatalogs = new List<AssemblyCatalog>(); foreach(var a in assemblies) { assCatalogs.Add(new AssemblyCatalog(a)); } if (mocksProvider != null) { var providers = new List<ExportProvider>(); providers.Add(mocksProvider); //need to use the mocks provider before the assembly ones foreach (var ac in assCatalogs) { var assemblyProvider = new CatalogExportProvider(ac); providers.Add(assemblyProvider); } container = new CompositionContainer(providers.ToArray()); foreach (var p in providers) //must set the source provider for CatalogExportProvider back to the container (kinda stupid but apparently no way around this) { if (p is CatalogExportProvider) { ((CatalogExportProvider)p).SourceProvider = container; } } } else { container = new CompositionContainer(new AggregateCatalog(assCatalogs)); } container.ComposeParts(this); } 

Additional information about my post: https://yoavniran.wordpress.com/2012/10/18/unit-testing-wcf-and-mef/

0
source

Source: https://habr.com/ru/post/1310020/


All Articles