Skip to content

Loading…

Fakes can't be serialized in the IL-merged version #74

Closed
patrik-hagne opened this Issue · 10 comments

2 participants

@patrik-hagne
FakeItEasy member

The below example fails with the following error message:

Attempt by method 'Castle.Proxies.PersonProxy.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' to access method 'Castle.DynamicProxy.Generators.Emitters.TypeUtil.Sort(System.Reflection.MemberInfo[])' failed.

 class Program
{
    static void Main(string[] args)
    {
        var person = A.Fake<Person>();

        var formatter = new BinaryFormatter();
        using (var stream = new MemoryStream())
        {
            formatter.Serialize(stream, person);
        }

    }
}

[Serializable]
public class Person
{}

There are tests that asserts that fakes can be serialized so this must have to do with the IL-merge.


Will be released as patch 1.9.1.

  • change version.txt to patch version
  • nuspec - update releaseNotes
  • push to upstream branch, check build
  • push nuget package
  • add tag to commit, push to upstream branch
  • create PR to upstream master, check build, merge PR, check build, delete branch
  • tweet ;-)
@adamralph
FakeItEasy member

Where are the tests for fake serialization? All the tests are running against the merged assembly and they are all passing.

However, you're right that your example doesn't work. If I remove the internalize switch from the merge then it does work, so I guess it's a matter of making some other Castle.Core type public. I'm looking into it...

@patrik-hagne
FakeItEasy member

CastleDynamicProxyGeneratorTests.Generated_proxies_should_be_serializable

@adamralph
FakeItEasy member

OK, the plot thickens. Inspection of the TargetSite property of the exception reveals that PersonProxy is "Castle.Proxies.PersonProxy, DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null". Note that this assembly is not signed, because the assembly where I wrote the test (FakeItEasy.IntegrationTests) is not signed.

However, when I run the same test from FakeItEasy.Tests, PersonProxy is "Castle.Proxies.PersonProxy, DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69" because FakeItEasy.Tests is signed.

This is the reason that CastleDynamicProxyGeneratorTests.Generated_proxies_should_be_serializable() passes. It is written in FakeItEasy.Tests.

The reason the tests pass when DynamicProxyGenAssembly2 is signed and failing when it is not is because we have

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

I'm not yet sure what the solution is.

@adamralph
FakeItEasy member

I now understand this comment http://old.nabble.com/Internalizing-Castle.Core-in-other-Assemblies-td30916966.html#a30921258

  • for mocking not-strong-named assemblies, I would need a build of NMock that uses InternalsVisibleTo("DynamicProxyGenAssembly2"),
  • whereas I would need a build of NMock that uses InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=...") to mock a strong-named assembly.

I wouldn't be surprised if Moq, NSubstitute, NMock and RhinoMocks all have the same issue as we are seeing here.

@adamralph
FakeItEasy member

A potential fix for this is to add Castle.DynamicProxy.Generators.Emitters.TypeUtil to the list of types excluded from internalization. I've tested this and it works.

If we're happy with this fix then I'll go ahead and patch 1.9.0 to 1.9.1.

I must say, I'm a little uncomfortable with this 'piecemeal' discovery of 'things in Castle.Core which need to be public'. If we come across another example, I think we should investigate a solution other than merging Castle.Core. Perhaps inclusion of Castle.Core source with namespace transformation. In fact, if that's a route we choose to go down, we should raise a feature request with Castle to produce a source code package with namespace transformations built in.

@patrik-hagne
FakeItEasy member

I might go as far as just cherry pick the pieces of dynamic proxy from Castle.Core that we want. Keep them completely internal to FIE. It should be a very small subset that we need. The potential downside is that it will be harder to get bug-fixes from Castle.Core into our code base.

@adamralph adamralph was assigned
@adamralph adamralph added a commit that referenced this issue
@adamralph adamralph #74 add failing test 0e237ea
@adamralph adamralph closed this
@adamralph adamralph referenced this issue
Closed

1.10.0-beta03 release #77

4 of 4 tasks complete
@patrik-hagne
FakeItEasy member

Tested this in the big project where I originally found the bug and I can confirm that it works now.

@adamralph
FakeItEasy member

Great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.