Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock ISerializable classes with Moq?

I'm completly new to Moq and now trying to create a mock for System.Reflection.Assembly class. I'm using this code:

var mockAssembly = new Mock<Assembly>(); 
mockAssembly.Setup( x => x.GetTypes() ).Returns( new Type[] { 
    typeof( Type1 ), 
    typeof( Type2 ) 
} );

But when I run tests I get next exception:

System.ArgumentException : The type System.Reflection.Assembly 
implements ISerializable, but failed to provide a deserialization 
constructor 
Stack Trace: 
   at 
Castle.DynamicProxy.Generators.BaseProxyGenerator.VerifyIfBaseImplementsGet­ObjectData(Type 
baseType) 
   at 
Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type[] 
interfaces, ProxyGenerationOptions options) 
   at Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxy(Type 
classToProxy, Type[] additionalInterfacesToProxy, 
ProxyGenerationOptions options) 
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type 
classToProxy, Type[] additionalInterfacesToProxy, 
ProxyGenerationOptions options, Object[] constructorArguments, 
IInterceptor[] interceptors) 
   at Moq.Proxy.CastleProxyFactory.CreateProxy[T](ICallInterceptor 
interceptor, Type[] interfaces, Object[] arguments) 
   at Moq.Mock`1.<InitializeInstance>b__0() 
   at Moq.PexProtector.Invoke(Action action) 
   at Moq.Mock`1.InitializeInstance() 
   at Moq.Mock`1.OnGetObject() 
   at Moq.Mock`1.get_Object() 

Could you reccomend me the right way to mock ISerializable classes (like System.Reflection.Assembly) with Moq.

Thanks in advance!

like image 714
sam Avatar asked Apr 23 '10 04:04

sam


5 Answers

System.Reflection.Assembly is abstract, so you can't create a new instance of it. However, you could create a test class which does and Mock that.

Example:

[TestMethod]
public void TestSomethingThatNeedsAMockAssembly()
{
    string title = "title";
var mockAssembly = new Mock();
mockAssembly.Setup(a => a.GetCustomAttributes(It.Is(s => s == Type.GetType("System.Reflection.AssemblyTitleAttribute")), It.IsAny())).Returns(new System.Attribute[] { new AssemblyTitleAttribute(title) } ); var c = new ClassThatTakesAssemblyAndParsesIt(mockAssembly.Object); Assert.IsTrue(c.AssemblyTitle == title); //etc } public class TestAssembly : Assembly { public TestAssembly() { //could probably do something interesting here } }

like image 188
Chuck Rostance Avatar answered Nov 07 '22 03:11

Chuck Rostance


The issue is not with ISerializable interface. You can mock ISerializable classes.

Notice the exception message:

The type System.Reflection.Assembly implements ISerializable, but failed to provide a deserialization constructor

Problem is, that Assembly does not provide deserialization constructor.

like image 31
Krzysztof Kozmic Avatar answered Nov 07 '22 03:11

Krzysztof Kozmic


As explained already, the problem is Assembly not exposing a deserialization constructor. This does not mean it can't be done though.

A solution using Moq as per your example would be:

    var mock = new Mock<_Assembly>();
    result.Setup(/* do whatever here as usual*/);

Note that to use _Assembly you will need to reference System.Runtime.InteropServices

like image 40
nathanchere Avatar answered Nov 07 '22 01:11

nathanchere


Instead of a mock you could try creating a dynamic assembly and build from that.

var appDomain = AppDomain.CurrentDomain;
var assembly = appDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.ReflectionOnly);
like image 1
Michiel van Oosterhout Avatar answered Nov 07 '22 02:11

Michiel van Oosterhout


I just needed to verify an embedded resource worked correctly; this worked for my situation:

    public class MockableAssembly : Assembly { }

    [TestClass]
    public class ApplicationSetupTests
    {
        [TestMethod]
        public void ApplyAsposeLicense_Success()
        {
            var mockAssembly = new Mock<MockableAssembly>();
            mockAssembly.Setup(a => a.GetManifestResourceStream(It.IsAny<string>())).Returns(mockedData);

            MethodIAmTesting(mockAssembly.Object);

            mockAssembly.Verify(a => a.GetManifestResourceStream("myString"), Times.Once);
        }
like image 1
John Avatar answered Nov 07 '22 01:11

John