How can I mock/fake/stub sealed OracleException with no public constructor?

青春壹個敷衍的年華 提交于 2019-12-08 15:50:27

问题


In my tests I need to test what happens when an OracleException is thrown (due to a stored procedure failure). I am trying to setup Rhino Mocks to

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

For whatever reason however, OracleException seems to be sealed with no public constructor. What can I do to test this?

Edit: Here is exactly what I'm trying to instantiate:

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

回答1:


It seems that Oracle changed their constructors in later versions, therefore the solution above will not work.

If you only want to set the error code, the following will do the trick for 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 });



回答2:


For oracle's managed data access (v 4.121.1.0) the constructor changed again

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, "", "", "" });



回答3:


Here is how you do it:

    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 });

Thanks to all that helped, you have been upvoted




回答4:


I'm using the Oracle.DataAccess.Client data provider client. I am having trouble constructing a new instance of an OracleException object, but it keeps telling me that there are no public constructors. I tried all of the ideas shown above and keep getting a null reference exception.

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);

When debugging the test code, I always get a NULL value for 'ci'.

Has Oracle changed the library to not allow this? What am I doing wrong and what do I need to do to instantiate an OracleException object to use with NMock?

By the way, I'm using the Client library for version 10g.

Thanks,

Charlie




回答5:


Use reflection to instantiate OracleException. See this blog post




回答6:


Use reflection to instantiate the OracleException object? Replace

new OracleException()

with

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



回答7:


You can always get all the constructors like this

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

For Oracle.DataAccess 4.112.3.0 this returned 7 constructors

The one I wanted was the second one in the list which took 5 arguments, int, string, string, string, int. I was surprised by the fifth argument because in ILSpy it looked like this

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));
}

So, to get the constructor I wanted I ended up using

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



回答8:


Good solution George. This also works for SqlException too:

        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 } );

-dave




回答9:


Can you write a trivial stored procedure that fails/errors each time, then use that to test?



来源:https://stackoverflow.com/questions/122215/how-can-i-mock-fake-stub-sealed-oracleexception-with-no-public-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!