Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

nuget-installed ninject.extensions.factory fails under ncrunch
jamesmanning
#1 Posted : Sunday, May 20, 2012 5:10:56 PM(UTC)
Rank: Member

Groups: Registered
Joined: 5/7/2012(UTC)
Posts: 17
Location: Raleigh, NC

Was thanked: 1 time(s) in 1 post(s)

Post #1,000 in this forum! :)


I'm hitting the same issue as this SO thread from 5 days ago:

http://stackoverflow.com...t-tests-but-not-ncrunch

Specifically, when run by NCrunch, my test has this exception:

Quote:

Ninject.ActivationException: Error activating IInterceptor using conditional implicit self-binding of IInterceptor


Remo (ninject dev, and author of the extension) responded with:

Quote:

The FuncModule is not loaded when running with that TestRunner. This happens in case the extension is not copied to the startup directory of the executed process.


Is this something fixable with NCrunch?
Remco
#2 Posted : Sunday, May 20, 2012 8:27:17 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Hi James -

I believe so. I'm not familiar with this framework myself but based on the comment of the author my expectation is that it is loading assemblies into the app domain dynamically, with the expectation that they exist in the same directory as the executing DLL.

Have a look at the wiki under 'Assumptions About Referenced Assembly Locations'. I believe this is the same problem as the one described, and can likely only be fixed by either changing the way that ninject is finding/loading the assembly, or by turning on the 'Copy Referenced Assemblies To Workspace' setting.


Cheers,

Remco
jamesmanning
#3 Posted : Monday, May 21, 2012 2:10:07 PM(UTC)
Rank: Member

Groups: Registered
Joined: 5/7/2012(UTC)
Posts: 17
Location: Raleigh, NC

Was thanked: 1 time(s) in 1 post(s)
Remco;1917 wrote:
[...] or by turning on the 'Copy Referenced Assemblies To Workspace' setting.


Unfortunately, I tried setting this (on both the unit test project and the class library project it's testing) but it still showed the same problem.

After a bunch of debugging, the root cause seems to be how the Ninject automatic module registration works - specifically, where it looks.

The key bit is in the ModuleLoader class:

https://github.com/ninje...les/ModuleLoader.cs#L77

It searches based on
Code:
AppDomain.CurrentDomain.BaseDirectory


While running under MSTest or the R# runner, that property points to the 'normal' build output directory for the test project (...\Foo.Tests\bin\Debug)

However, when running under NCrunch, it's somewhere under the NCrunch working directory - in my testing,
Code:
C:\Users\james\AppData\Local\NCrunch\2952\50\TestResults\6696e3c6-f2a0-40d7-af01-97c56fc50bd2\Out


Does NCrunch use separate AppDomain's, or are all the test runs done in a single one? In any case, if there's some way to get the AppDomain's BaseDirectory to be a place that has the assemblies used during the test (instead of that output directory), it would at least fix the users of Ninject. :)

Is there some different place it could/should look? I'm not sure Ninject would change behavior since it works for runners like R#, but it's worth a shot. :)
Remco
#4 Posted : Monday, May 21, 2012 8:30:45 PM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Hi James -

Nice analysis!

Are you able to let me know which version of MSTest you were checking this behaviour against? Or whether you have any custom configuration that might affect it? When I test locally with MSTest under VS2010, it always sets the application base directory to be equal to the MSTest workspace (not the bin\debug directory).
jamesmanning
#5 Posted : Monday, May 21, 2012 9:04:07 PM(UTC)
Rank: Member

Groups: Registered
Joined: 5/7/2012(UTC)
Posts: 17
Location: Raleigh, NC

Was thanked: 1 time(s) in 1 post(s)
This is VS11 Beta with the April update applied. The version from the cmdline says:

Quote:
Microsoft (R) Test Execution Command Line Tool Version 11.0.50214.1
Copyright (c) Microsoft Corporation. All rights reserved.


I'm able to repro the behavior starting 'from scratch' (a freshly started VS11 instance, no solution open) by doing these steps:


  1. create new unit test project/sln (ctrl+shift+n)
  2. after it's created, go into 'manage nuget packages' to install ninject.extensions.factory
  3. add a little bit of code to the UnitTest1.cs that was created as part of the project


Here's the full source for the UnitTest1.cs:


Code:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ninject;
using Ninject.Extensions.Factory;

namespace TestOfNCrunchWithFactory
{
    public interface IFoo {}
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var kernel = new StandardKernel();
            kernel.Bind<IFoo>().ToFactory();
            kernel.Get<IFoo>();
        }
    }
}


in the debugger watch window, I can see that under NCrunch, the AppDomain.CurrentDomain.BaseDirectory is C:\Users\james\AppData\Local\NCrunch\20468\4\TestResults\965f4516-9da1-4433-9b75-3b3d1dd933c7\Out
jamesmanning
#6 Posted : Monday, May 21, 2012 9:16:59 PM(UTC)
Rank: Member

Groups: Registered
Joined: 5/7/2012(UTC)
Posts: 17
Location: Raleigh, NC

Was thanked: 1 time(s) in 1 post(s)
I was able to repro this with VS2010 as well - same behavior, and the BaseDirectory was C:\Users\james\AppData\Local\NCrunch\9348\1\TestResults\0b2a40ad-0fe7-4ed2-a106-35e581a0f819\Out

R# isn't installed/running in my VS2010

NCrunch version (I just installed it) is 1.39.0.15b

I even re-ran through the NCrunch configuration wizard and accepted every default but I still get the same behavior.
Remco
#7 Posted : Tuesday, May 22, 2012 12:12:34 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Hi James,

Sorry - I've just re-read my post and realised that I didn't make it completely clear what I was asking.

NCrunch sets the base directory to be equal to the MSTest working directory exactly as you've described. This is by design and is exactly as you've described it. It also is (in some manner of perspective) a source for the Ninject problems.

When testing MSTest tests using the Visual Studio test runner, I observe behaviour identical to the above. MSTest in VS2010 appears to set the app domain base directory to its working directory (the 'Out' dir). This means that the behaviour of MSTest and the R# test runner are not consistent.

The reason Ninject is working under the Visual Studio MSTest runner is because the Visual Studio MSTest runner copies ALL the build output files into the 'Out' directory prior to a test beginning execution. NCrunch currently does not.

So it seems to me that the correct fix to this would be to change the NCrunch test runner so that it copies the build output files in the same manner as Visual Studio's MSTest runner, thus making the behaviour consistent.

Something you can try which may allow you to work around the problem (though I'm not sure as to its technical messiness/feasibility) is to place DeploymentItem attributes for build outputs on tests that are using the Ninject framework to resolve dependencies. If nothing else, this should help to confirm the above. For example:

[TestClass]
[DeploymentItem("ThisExecutingAssembly.dll")]
[DeploymentItem("AnotherAssemblyThisDependsOn.dll")]
public class MyTestClass
{
[TestMethod]
public void MyTest()
{
... Insert normal ninject-dependent test code here ...
}
}

.. This will instruct NCrunch's MSTest runner to copy the build output files into the 'Out' dir along with other MSTest dependencies, thus emulating the normal VS MSTest behaviour.
Remco
#8 Posted : Tuesday, May 22, 2012 2:31:32 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
Ok, I take much of that last post back. It seems that MSTest is doing its best to make a fool out of me.

Apparently the BaseDirectory inside the Visual Studio MSTest app domain depends upon whether or not you have the 'Enable Deployment' option turned on inside your MSTest configuration. If your MSTest domain has this option turned off, then it's likely that you won't be seeing the behaviour I've described in the previous post.

Other test runners do not always appear to match this behaviour.

So I'm going to change NCrunch so that it will always set the AppDomain.BaseDirectory to be the same as test project's build output directory. IMHO this is more useful and it will also solve your problem.
jamesmanning
#9 Posted : Tuesday, May 22, 2012 3:27:11 AM(UTC)
Rank: Member

Groups: Registered
Joined: 5/7/2012(UTC)
Posts: 17
Location: Raleigh, NC

Was thanked: 1 time(s) in 1 post(s)
awesome, thanks!

It's probably a bad idea for lots of reasons, but just to throw it out there, I wondered if the first time during a given run (inside a given VS instance) you could run a 'fake' test in the framework being used (didn't do any asserts, just ran and sent you back some info) to tell you things about the test environment (BaseDirectory for this case, but potentially also things like assemblies loaded as well) and then use those as a guide on what NCrunch sets.

At least the theory would be that you then wouldn't have to keep up with what each framework does (especially if it varies by version or over time), you'd just need to potentially add to the set of things you 'inspect' in order to mimic the existing framework.

Just a thought, and like I said, most likely a very bad one. :)
Remco
#10 Posted : Tuesday, May 22, 2012 4:46:50 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
This isn't at all a bad idea, although as I'm sure you can imagine it would be difficult to create a clean and consistent implementation. One of the things I have considered is to introduce an 'auto configure' mode that would do something similar to what you've described, and set a bunch of configuration options based on information retrieved from the runtime test environment. Of course, it's still a long way off... I meanwhile hold a secret (but probably futile) hope that most of these test frameworks are stabilising and won't be seeing many more big structural changes...
jamesmanning
#11 Posted : Tuesday, May 22, 2012 4:53:37 AM(UTC)
Rank: Member

Groups: Registered
Joined: 5/7/2012(UTC)
Posts: 17
Location: Raleigh, NC

Was thanked: 1 time(s) in 1 post(s)
actually, I would think (hope?) that the frameworks will all have a big change upcoming with pervasive async. MSTest has already started supporting it, but I'd imagine there will need to be more test framework support for things that orchestrate or start multiple async operations (Task or otherwise). Guess we'll see :)
Remco
#12 Posted : Tuesday, June 19, 2012 4:40:56 AM(UTC)
Rank: NCrunch Developer

Groups: Administrators
Joined: 4/16/2011(UTC)
Posts: 7,161

Thanks: 964 times
Was thanked: 1296 time(s) in 1202 post(s)
For anyone interested, 1.40b has just been released including a change that sets the MSTest base directory to be equal to the build output directory (as described above). Hopefully this should help with resolving runtime referencing issues and align NCrunch more closely with other test runners.
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

YAF | YAF © 2003-2011, Yet Another Forum.NET
This page was generated in 0.074 seconds.
Trial NCrunch
Take NCrunch for a spin
Do your fingers a favour and supercharge your testing workflow
Free Download