创建SqlCeLockTimeoutException实例

本文关键字:实例 SqlCeLockTimeoutException 创建 | 更新日期: 2023-09-27 18:03:37

出于单元测试的目的,我想创建一个类型为SqlCeLockTimeoutException的模拟对象

因为它的构造函数是受保护的,所以我在测试中创建了一个扩展类:
[Serializable]
private class TestableSqlCeLockTimeoutException : SqlCeLockTimeoutException
{
    public TestableSqlCeLockTimeoutException()
           : this(new SerializationInfo(typeof (TestableSqlCeLockTimeoutException), 
                                        new FormatterConverter()), 
                  new StreamingContext())
    {
    }
    protected TestableSqlCeLockTimeoutException(SerializationInfo info,
                                                StreamingContext context) 
           : base(info, context)
    {
    }
}

但是,在创建实例时,我一直得到以下异常:

测试方法Foo抛出异常:
system . runtime . serializize . serializationexception: Member 'ClassName' not found.

为什么我总是收到它?我试着玩Serializable属性,但无济于事。

创建SqlCeLockTimeoutException实例

@Mugan你问了一个非常有趣的问题!为了回答这个问题,我不得不反编译SqlCeLockTimeoutException。当我试图帮助你的时候,我学到了很多。谢谢你。

由于System.Exception C 'tor需要对某些属性进行反序列化而出现问题:

[System.Security.SecuritySafeCritical]  // auto-generated
protected Exception(SerializationInfo info, StreamingContext context) 
{
 //some validation
    _className = info.GetString("ClassName");
    _message = info.GetString("Message");
    _data = (IDictionary)(info.GetValueNoThrow("Data",typeof(IDictionary)));
    _innerException = (Exception)(info.GetValue("InnerException",typeof(Exception)));
    _helpURL = info.GetString("HelpURL");
    _stackTraceString = info.GetString("StackTraceString");
    _remoteStackTraceString = info.GetString("RemoteStackTraceString");
    _remoteStackIndex = info.GetInt32("RemoteStackIndex");
    _exceptionMethodString = (String)(info.GetValue("ExceptionMethod",typeof(String)));
    HResult = info.GetInt32("HResult");
    _source = info.GetString("Source");
//some bla bla....

为了解决上述问题,我将受保护的C 'tor更改为public,然后使用它:

var info = new SerializationInfo(typeof (TestableSqlCeLockTimeoutException), 
           new FormatterConverter());
info.AddValue("ClassName", string.Empty);
info.AddValue("Message", string.Empty);
info.AddValue("InnerException", new ArgumentException());
info.AddValue("HelpURL", string.Empty);
info.AddValue("StackTraceString", string.Empty);
info.AddValue("RemoteStackTraceString", string.Empty);
info.AddValue("RemoteStackIndex", 0);
info.AddValue("ExceptionMethod", string.Empty);
info.AddValue("HResult", 1);
info.AddValue("Source", string.Empty);
new TestableSqlCeLockTimeoutException(info,new StreamingContext());

那么这次从SqlCeException引发了新的异常。SqlCeException也需要一个属性__Errors__:

protected SqlCeException(SerializationInfo info, StreamingContext context)
  : base(info, context)
{
  if (info == null)
    throw new ArgumentNullException("info");
  this.Errors = (SqlCeErrorCollection) info.GetValue("__Errors__", typeof (SqlCeErrorCollection));
}

SqlCeErrorCollection Ctor是内部的,因此我使用Reflaction创建一个实例:

BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
CultureInfo culture = null; // use InvariantCulture or other if you prefer
object instantiatedType =
       Activator.CreateInstance(typeof(SqlCeErrorCollection), flags, null, null, culture);
info.AddValue("__Errors__", instantiatedType);

现在一切正常。最后是一个创建方法:

private static SqlCeLockTimeoutException CreateSqlCeLockTimeoutExceptionForTest()
{
    var info = new SerializationInfo(typeof (TestableSqlCeLockTimeoutException), 
               new FormatterConverter());
    info.AddValue("ClassName", string.Empty);
    info.AddValue("Message", string.Empty);
    info.AddValue("InnerException", new ArgumentException());
    info.AddValue("HelpURL", string.Empty);
    info.AddValue("StackTraceString", string.Empty);
    info.AddValue("RemoteStackTraceString", string.Empty);
    info.AddValue("RemoteStackIndex", 0);
    info.AddValue("ExceptionMethod", string.Empty);
    info.AddValue("HResult", 1);
    info.AddValue("Source", string.Empty);
    BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
    CultureInfo culture = null; // use InvariantCulture or other if you prefer
    object instantiatedType = Activator.CreateInstance(typeof (SqlCeErrorCollection), 
                                flags, null, null, culture);
    info.AddValue("__Errors__", instantiatedType);
    return new TestableSqlCeLockTimeoutException(info, new StreamingContext());
}

还有一件事,您可以使用Reflaction来创建SqlCeLockTimeoutException的新实例,而不是TestableSqlCeLockTimeoutException:

private static SqlCeLockTimeoutException CreateSqlCeLockTimeoutExceptionForTest()
{
    BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
    CultureInfo culture = null; // use InvariantCulture or other if you prefer
    object instantiatedType = Activator.CreateInstance(typeof (SqlCeErrorCollection), 
                  flags, null, null, culture);
    object result = Activator.CreateInstance(typeof(SqlCeLockTimeoutException), 
                  flags, null, new []{instantiatedType}, culture);
    return (SqlCeLockTimeoutException)result;
}
    [Fact]
    public void ConstructTest2()
    {
        var info = new SerializationInfo(typeof(CvmpApplicationException), new MyFormatConverter());
        info.AddValue("ClassName", typeof(CvmpApplicationException).FullName);
        info.AddValue("Message", "test");
        info.AddValue("InnerException", new Exception());
        info.AddValue("HelpURL", string.Empty);
        info.AddValue("StackTraceString", string.Empty);
        info.AddValue("RemoteStackTraceString", string.Empty);
        info.AddValue("RemoteStackIndex", 0);
        info.AddValue("ExceptionMethod", string.Empty);
        info.AddValue("HResult", 1);
        info.AddValue("Source", string.Empty);
        _ = new TestCvmpApplicationException(
            info,
            new StreamingContext(StreamingContextStates.All));
    }
    private class MyFormatConverter : IFormatterConverter
    {
        public object Convert(object value, Type type)
        {
            return value;
        }
        public object Convert(object value, TypeCode typeCode)
        {
            return value;
        }
        public bool ToBoolean(object value)
        {
            return true;
        }
        public byte ToByte(object value)
        {
            return 1;
        }
        public char ToChar(object value)
        {
            throw new NotImplementedException();
        }
        public DateTime ToDateTime(object value)
        {
            return DateTime.Now;
        }
        public decimal ToDecimal(object value)
        {
            return 1;
        }
        public double ToDouble(object value)
        {
            return 1D;
        }
        public short ToInt16(object value)
        {
            return 1;
        }
        public int ToInt32(object value)
        {
            return 1;
        }
        public long ToInt64(object value)
        {
            return 1;
        }
        public sbyte ToSByte(object value)
        {
            return 1;
        }
        public float ToSingle(object value)
        {
            return 1;
        }
        public string? ToString(object value)
        {
            return "Message";
        }
        public ushort ToUInt16(object value)
        {
            return 1;
        }
        public uint ToUInt32(object value)
        {
            return 1;
        }
        public ulong ToUInt64(object value)
        {
            return 1;
        }
    }
    private class TestCvmpApplicationException : CvmpApplicationException
    {
        public TestCvmpApplicationException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    }