Come per deridere le classi ISerializable con Moq?
-
01-10-2019 - |
Domanda
Sono completamente nuovo a Moq e ora cercando di creare un finto per
Classe System.Reflection.Assembly
. Sto usando questo codice:
var mockAssembly = new Mock<Assembly>();
mockAssembly.Setup( x => x.GetTypes() ).Returns( new Type[] {
typeof( Type1 ),
typeof( Type2 )
} );
Ma quando ho eseguito i test ottengo eccezione successiva:
System.ArgumentException : The type System.Reflection.Assembly
implements ISerializable, but failed to provide a deserialization
constructor
Stack Trace:
at
Castle.DynamicProxy.Generators.BaseProxyGenerator.VerifyIfBaseImplementsGetObjectData(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()
Mi può consigliare il modo giusto per classi ISerializable
finti
(Come System.Reflection.Assembly
) con Moq.
Grazie in anticipo!
Soluzione
Il problema non è con ISerializable. È possono le classi ISerializable finte.
Si noti il ??messaggio di eccezione:
Il tipo System.Reflection.Assembly implementa ISerializable, ma non è riuscito fornire un deserializzazione costruttore
Il problema è che l'Assemblea non fornisce costruttore deserializzazione.
Altri suggerimenti
System.Reflection.Assembly è astratta, quindi non è possibile creare una nuova istanza di esso. Tuttavia, è possibile creare una classe di test che fa e che Mock.
Esempio:
[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 } }
Come spiegato già, il problema non è l'Assemblea esponendo un costruttore deserializzazione. Questo non significa che non si può fare però.
Una soluzione che utilizza Moq secondo il vostro esempio può essere:
var mock = new Mock<_Assembly>();
result.Setup(/* do whatever here as usual*/);
Si noti che per l'uso _Assembly
dovrai riferimento System.Runtime.InteropServices
Al posto di un mock si potrebbe provare a creare una dinamica di assemblaggio e costruzione da quello.
var appDomain = AppDomain.CurrentDomain;
var assembly = appDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.ReflectionOnly);
Ho appena bisogno di verificare una risorsa incorporata funzionato correttamente; questo ha lavorato per la mia situazione:
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);
}