I'm using Ploeh's SemanticComparison library with great success - except when I have an abstract class involved that doesn't expose all of its constructor arguments.
Here is the exception I get -
Ploeh.SemanticComparison.ProxyCreationException : The proxy of Foo could not be created using the same semantic heuristics as the default semantic comparison. In order to create proxies of types with non-parameterless constructor the values from the source constructor must be compatible to the parameters of the destination constructor.
----> System.InvalidOperationException : Operation is not valid due to the current state of the object.
Here is the simplest example I could come up with -
// this fails with the aforementioned exception
_fixture.Create<Foo>().AsSource().OfLikeness<Foo>().CreateProxy();
public class Foo : Bar
{
public Foo(int age)
: base(age)
{
}
}
public abstract class Bar
{
private readonly int _age;
protected Bar(int age)
{
_age = age;
}
}
However, if I add public int NotAge { get; set; }
to abstract class Bar
, then all is well. I really consider this a sub-optimal solution because I don't want to expose property age
. It's simply being used to calculate other things.
How can I resolve this without exposing properties just for the sake of testing. Is there perhaps another library that can achieve the same effect without this issue?
This error is raised when there was a problem fetching the properties of the destination class and matching to constructors of the source type, although the error reads as if only constructors were being mapped.
In your case, the inner exception is due to there being no public properties in either class. I'm pretty sure your fix just redirects the mapping to your dummy property.
You can fix it with public int age { get { return _age; } }
on the base class - in this example there's little harm.
The usual escape hatch for this sort of issue is to use InternalVisibleTo
but the libary currently uses only BindingFlags.Public
when mapping types so it would not see an internal property created for this purpose.
I was able to get a proxy to create by tweaking the source to use BindingFlags.NonPublic
in addition to BindingFlags.Public
but I'm not sure this is a sound approach.