Build/Test Issues

Ncrunch & Mef

Started by Connes on 5,318 views

Hi,

I some of my tests i inject a dependency by MEF with :

// In My TestClass
 [AssemblyInitialize]
        public static void InitializeAssembly(TestContext testContext)
        {
            // Add Task scheduler DAL assembly for MEF injection.
            Bootstrapper.ConfigureAggregateCatalog(new AssemblyCatalog(typeof(CommandManager).Assembly));
            Bootstrapper.ConfigureAggregateCatalog(new AssemblyCatalog(typeof(CommandAdapterDataAccessMock).Assembly));

            // Configures recomposition container using MEF
            Bootstrapper.ConfigureContainer();
        }
...
 // In the tested class.
        [Import]
        private IIngestionDataAccessFactory factory;
public DataIngestionService()
        {
            Bootstrapper.SatisfyImportsOnce(this); // -> Boum
        }


If i run all the test in VS, all are green, in MsTest, all green but in NCrunch i get a composition Error:

System.ComponentModel.Composition.CompositionException: The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.

1) More than one export was found that matches the constraint:
ContractName Itesoft.ProductionManager.DataIngestion.Contracts.IIngestionDataAccessFactory
RequiredTypeIdentity Itesoft.ProductionManager.DataIngestion.Contracts.IIngestionDataAccessFactory

Resulting in: Cannot set import 'Itesoft.ProductionManager.DataIngestion.BLL.DataIngestionService.factory (ContractName="Itesoft.ProductionManager.DataIngestion.Contracts.IIngestionDataAccessFactory")' on part 'Itesoft.ProductionManager.DataIngestion.BLL.DataIngestionService'.
Element: Itesoft.ProductionManager.DataIngestion.BLL.DataIngestionService.factory (ContractName="Itesoft.ProductionManager.DataIngestion.Contracts.IIngestionDataAccessFactory") --> Itesoft.ProductionManager.DataIngestion.BLL.DataIngestionService


It 's seemed that several MEF exports are injected in the Container but only when they are runned in ncrunch. Is the handling of the AssemblyInitializeAttribute is different with NCrunch ?

If I run the test one by one in ncrunch, they are all ok, if i run all the tests at a time with 'Run test in new task runnerProcess' they are all KO.
How can i have more informations on what's happen ?

Thanks in advance
CConnes
Hi,

Thanks for sharing this issue.

These tests are likely to be sequence/batch dependent. Because NCrunch is able to call into test runners multiple times within the same process (as part of its task batching), it is possible for the Bootstrapper code above to be run multiple times for the same process.

Placing a static boolean check at the top of the InitializeAssembly method to ensure it doesn't execute multiple times should resolve this problem. See 'Test runner re-use' under http://www.ncrunch.net/documentation/considerations-and-constraints_test-atomicity for more information on this one.

Cheers,

Remco
Thanks a lot.
The static check made the trick but i would understand why the InitializeAssembly function is called several times ? The AssemblyInitialize attribute does not guarantee us to be called only once when assembly is loaded ?

CConnes
The repeated calls to AssemblyInitialize occur because of the behaviour of NCrunch's test pipeline. NCrunch will split the entire test queue into multiple tasks to be executed independently of one another. Because the execution of each task involves a full fresh call into the test framework, and the test framework is not designed to have its activities split between multiple invocations, it needs to be reinitialised for each task that is run. This results in AssemblyInitialize being called once per task, rather than once per process. The alternative is to terminate the process after each task run, but this is very expensive as the act of building and JITing assemblies into a process is very time consuming.

When you use a normal synchronous test runner, tests are run sequentially end-to-end in a single process within the lifespan of one control thread, and the process is torn down on test completion. This is a design that simply doesn't work for NCrunch, so the re-initialisation of the test framework is a concession made to allow NCrunch to run tests selectively without massive loss in performance.
Thanks a lot.
I have appreciated you take the time for a detailled response.

CConnes.

Post a reply

Log in to reply.