Build/Test Issues

Running tests on code using DelegateCompiler library

Started by bstenzel on 5,511 views

I'm using DelegateDecompiler to implement filtering on the db on computed properties. A simple test case:

using System.Linq;

using DelegateDecompiler;

using NUnit.Framework;

public class Person
{
	public string LastName { get; set; }

	public string FirstName { get; set; }

	[Computed]
	public string FullName
	{
		get
		{
			if (this.FirstName != null)
			{
				return this.FirstName + " " + this.LastName;
			}
			return this.LastName;
		}
	}
}

[TestFixture]
public class RepoTests
{
	[Test]
	public void TestDecompile()
	{
		Person[] persons = {
							  new Person { LastName = "Doe", FirstName = "John" },
							  new Person { LastName = "Dickerson" }
						  };

		Assert.DoesNotThrow(() => persons.AsQueryable()
									.Where(p => p.FullName.Contains("Doe"))
									.Decompile()
									.ToArray());
	}
}


Using e.g. the ReSharper test runner this test passes, but in NCrunch it fails with an InvalidOperationException with the message 'No coercion operator is defined between the types "System.Int32" and "System.Int32&." at System.Linq.Expressions.Expression.GetUserDefinedCoercionOrThrow. I'm baffled to be honest. No idea where the int is coming from, much less the nullable int. I tried to check out DelegateCompiler as a sub dependency in a test project to debug through it, but I didn't manage to get it to compile in NCrunch.

Similar code that actually queries a database also runs, so I assume DelegateDecompiler is not at fault here. It does reverse-engineer expressions from generated IL code, though, and as far as I am aware NCrunch is pretty special (also extremely fast) as it uses its own builds. I guess that's somehow related to the issue.

Any input on how to get this to run would be appreciated.
Hi, thanks for sharing this issue.

I don't have any firsthand experience with DelegateDecompiler, but based on what you've described, it looks as though this tool is making use of an IL-analysis step, either inside the build process for your project or possibly at run time.

NCrunch collects its code coverage and performance data from your code by instrumenting it at build time. Basically, it picks up the .DLL after the compiler has built it, and adds a whole range of additional IL instructions that enable it to track the way your code behaves under execution. The injected IL is designed as much as possible not to change the behaviour of your code in any way, but it does still physically change the code. I don't doubt that the DelegateDecompiler tool is picking up NCrunch's instrumentation and not making sense of it.

There isn't really any way for NCrunch to internally handle a situation like this, as it has no power over tools that disassemble instrumented code. There are two ways you can work around this problem:

1. Suppress NCrunch's instrumentation for the decompiled methods using code coverage suppression comments. This will allow you to select targeted areas of your code that you don't want to have instrumented, so that they don't interefere with DelegateDecompiler.

2. Turn off NCrunch's instrumentation for the projects involved using the instrument output assembly project-level configuration setting.

Note that both of the above workarounds will result in the loss of code coverage data collected by NCrunch.
Thanks for your quick reply. Again you're spot-on. Fortunately it was enough to disable instrumentation on our project for the db entities, so we still have coverage data for everything containing actual business logic.

Thanks for a great tool and great support.

Post a reply

Log in to reply.