【问题标题】:How can I mock/fake/stub sealed OracleException with no public constructor?如何在没有公共构造函数的情况下模拟/伪造/存根密封 OracleException?
【发布时间】:2010-09-12 10:35:04
【问题描述】:

在我的测试中,我需要测试抛出 OracleException 时会发生什么(由于存储过程失败)。我正在尝试将 Rhino Mocks 设置为

Expect.Call(....).Throw(new OracleException());

然而,无论出于何种原因,OracleException 似乎被密封,没有公共构造函数。我可以做些什么来测试这个?

编辑:这正是我要实例化的内容:

public sealed class OracleException : DbException {
  private OracleException(string message, int code) { ...}
}

【问题讨论】:

    标签: c# .net oracle mocking oracleclient


    【解决方案1】:

    你总是可以像这样得到所有的构造函数

    ConstructorInfo[] all = typeof(OracleException).GetConstructors(
      BindingFlags.NonPublic | BindingFlags.Instance);`
    

    对于Oracle.DataAccess 4.112.3.0,这返回了 7 个构造函数

    我想要的是列表中的第二个,它有 5 个参数,int, string, string, string, int。我对第五个参数感到惊讶,因为在 ILSpy 中它看起来像这样

    internal OracleException(int errCode, string dataSrc, string procedure, string errMsg)
    {
        this.m_errors = new OracleErrorCollection();
        this.m_errors.Add(new OracleError(errCode, dataSrc, procedure, errMsg));
    }
    

    所以,为了获得我想要的构造函数,我最终使用了

    ConstructorInfo constructorInfo =
      typeof(OracleException).GetConstructor(
        BindingFlags.NonPublic | BindingFlags.Instance,
        null,
        new Type[] { typeof(int), typeof(string), typeof(string), typeof(string), typeof(int) },
        null);`
    

    【讨论】:

      【解决方案2】:

      对于 oracle 的托管数据访问 (v 4.121.1.0),构造函数再次更改

      var ci = typeof(OracleException).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(int), typeof(string), typeof(string), typeof(string) }, null);
      var c = (OracleException)ci.Invoke(new object[] { 1234, "", "", "" });
      

      【讨论】:

      • ddtek 4.2.0.0 我该怎么做?我是 refleciton 的新手,我无法识别任何构造函数
      【解决方案3】:

      好像Oracle在后来的版本中改变了他们的构造函数,所以上面的解决方案是行不通的。

      如果您只想设置错误代码,以下将解决 2.111.7.20 的问题:

      ConstructorInfo ci = typeof(OracleException)
                  .GetConstructor(
                      BindingFlags.NonPublic | BindingFlags.Instance, 
                      null, 
                      new Type[] { typeof(int) }, 
                      null
                      );
      
      Exception ex = (OracleException)ci.Invoke(new object[] { 3113 });
      

      【讨论】:

        【解决方案4】:

        使用反射来实例化 OracleException。见this blog post

        【讨论】:

          【解决方案5】:

          我正在使用 Oracle.DataAccess.Client 数据提供程序客户端。我在构造 OracleException 对象的新实例时遇到问题,但它一直告诉我没有公共构造函数。我尝试了上面显示的所有想法并不断收到空引用异常。

          object[] args = { 1, "Test Message" };
          ConstructorInfo ci = typeof(OracleException).GetConstructor(BindingFlags.NonPublic 
               | BindingFlags.Instance, null, System.Type.GetTypeArray(args), null);
          var e = (OracleException)ci.Invoke(args);
          

          在调试测试代码时,我总是得到 'ci' 的 NULL 值。

          Oracle 是否已将库更改为不允许这样做?我做错了什么,我需要做什么来实例化一个 OracleException 对象以与 NMock 一起使用?

          顺便说一下,我使用的是 10g 版本的客户端库。

          谢谢,

          查理

          【讨论】:

            【解决方案6】:

            很好的解决方案乔治。这也适用于 SqlException:

                    ConstructorInfo ci = typeof( SqlErrorCollection ).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] {  }, null );
                    SqlErrorCollection errorCollection = (SqlErrorCollection) ci.Invoke(new object[]{});
            
                    ci = typeof( SqlException ).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof( string ), typeof( SqlErrorCollection ) }, null );
                    return (SqlException) ci.Invoke( new object[] { "some message", errorCollection } );
            

            -戴夫

            【讨论】:

              【解决方案7】:

              这是你的做法:

                  ConstructorInfo ci = typeof(OracleException).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] {typeof(string), typeof(int)}, null);
                  var c = (OracleException)ci.Invoke(new object[] { "some message", 123 });
              

              感谢所有帮助,您已被支持

              【讨论】:

                【解决方案8】:

                使用反射来实例化 OracleException 对象?替换

                new OracleException()
                

                object[] args = ... ;
                (OracleException)Activator.CreateInstance(typeof(OracleException), args)
                

                【讨论】:

                • 这似乎可以工作,我如何指定构造函数参数?
                • Activator.CreateInstance(typeof(OracleException), new object[] {yourParams});
                【解决方案9】:

                你能写一个每次都失败/错误的简单存储过程,然后用它来测试吗?

                【讨论】:

                • 我不想每次都打数据库!
                猜你喜欢
                • 2012-02-27
                • 2021-07-20
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-11-24
                • 1970-01-01
                • 2011-04-03
                • 1970-01-01
                相关资源
                最近更新 更多