4

I set up a simple test project in Visual Studio 2010. For unit tests I use nunit 2.6.1 and for mocking FakeItEasy 1.7.4582.63 which I install via NuGet.

I try to fake a DbDataAdapter using the following code:

using System.Data.Common;
using FakeItEasy;
using NUnit.Framework;

namespace huhu
{
    [TestFixture]
    public class Class1
    {
        [Test]
        public void test1()
        {
            A.Fake<DbDataAdapter>();
        }
    }
}

When I run the test using .NET framework 3.5 everything works fine and test1 will pass. But, when I set the framework version to .NET 4.0, I get the following exception:

FakeItEasy.Core.FakeCreationException : 
  Failed to create fake of type "System.Data.Common.DbDataAdapter".

  Below is a list of reasons for failure per attempted constructor:
    No constructor arguments failed:
      No default constructor was found on the type System.Data.Common.DbDataAdapter.
    The following constructors were not tried:
      (*System.Data.Common.DbDataAdapter)

      Types marked with * could not be resolved, register them in the current
      IFakeObjectContainer to enable these constructors.

Any ideas how to make things work in .NET 4.0 are appreciated!

Bye, Jörg

k.m
  • 30,794
  • 10
  • 62
  • 86
Joerg Reinhardt
  • 358
  • 4
  • 9

1 Answers1

4

Usually such problems come not from FakeItEasy itself, but from Castle.DynamicProxy, library which FakeItEasy uses to create fake types. Investigating this little further leads to following exception thrown by Castle:

Due to limitations in CLR, DynamicProxy was unable to successfully replicate non-inheritable attribute System.Security.Permissions.PermissionSetAttribute on System.Data.Common.DbDataAdapter.CloneInternals. To avoid this error you can chose not to replicate this attribute type by calling 'Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(typeof(System.Security.Permissions.PermissionSetAttribute))'.

Inspecting DbDataAdapter base class' source code (DataAdapter) shows that this indeed is the case:

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
protected virtual DataAdapter CloneInternals()

Castle already hinted how to solve this problem. Before creating your fake, simply instruct Castle not to replicate PermissionSetAttribute:

Castle.DynamicProxy.Generators
   .AttributesToAvoidReplicating.Add(typeof(PermissionSetAttribute));
var fake = A.Fake<DbDataAdapter>();

Two things to note:

  1. You need to reference Castle.Core.dll in your project (available here)
  2. Keep in mind FakeItEasy will only be able to mock virtual methods of this DbDataAdapter (again, this is Castle.DynamicProxy/CLR limitation - I briefly explained why this is the case in my blog post)
k.m
  • 30,794
  • 10
  • 62
  • 86
  • Gee! That helped! Thanks a lot! But, I'm still wondering why this exception is only thrown when I'm using .NET 4.0 - I have just set up the same test in a .NET 3.5 class library where the fake is generated without any complaint. I located DataAdapter.cs in the download .NET_3.5_sp1_redist from [Microsoft](http://referencesource.microsoft.com/netframework.aspx) and found the same PermissionSetAttribute... – Joerg Reinhardt Aug 13 '12 at 13:56
  • There were change is the class between 3.5 and 4.0 having to do with security. The added security in 4.0 is what caused your problem. – David Parvin Feb 25 '14 at 21:55