Как я могу смоделировать / фальсифицировать / заглушку в запечатанном OracleException без открытого конструктора? - PullRequest
9 голосов
/ 23 сентября 2008

В моих тестах мне нужно проверить, что происходит, когда генерируется исключение OracleException (из-за сбоя хранимой процедуры). Я пытаюсь настроить Rhino Mocks на

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

По какой-то причине OracleException, похоже, запечатан без открытого конструктора. Что я могу сделать, чтобы проверить это?

Редактировать: Вот именно то, что я пытаюсь создать:

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

Ответы [ 9 ]

6 голосов
/ 10 октября 2014

Для управляемого доступа к данным 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, "", "", "" });
5 голосов
/ 23 сентября 2008

Вот как вы это делаете:

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

Благодаря всему, что помогло, вы проголосовали

3 голосов
/ 06 мая 2011

Похоже, что 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 });
3 голосов
/ 01 июля 2010

Я использую клиент поставщика данных 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);

При отладке тестового кода я всегда получаю значение NULL для 'ci'.

Oracle изменил библиотеку, чтобы запретить это? Что я делаю неправильно и что мне нужно сделать, чтобы создать экземпляр объекта OracleException для использования с NMock?

Кстати, я использую клиентскую библиотеку для версии 10g.

Спасибо

Charlie

3 голосов
/ 23 сентября 2008

Использовать отражение для создания экземпляра OracleException. Смотрите это сообщение в блоге

2 голосов
/ 29 июня 2017

Вы всегда можете получить все конструкторы, подобные этому

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

Для Oracle.DataAccess 4.112.3.0 это вернуло 7 конструкторов

enter image description here

Тот, который я хотел, был вторым в списке, который принял 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 голосов
/ 23 сентября 2008

Использовать отражение для создания экземпляра объекта OracleException? Заменить

new OracleException()

с

object[] args = ... ;
(OracleException)Activator.CreateInstance(typeof(OracleException), args)
1 голос
/ 17 июня 2009

Хорошее решение, Джордж. Это также работает и для 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 } );

-dave

0 голосов
/ 23 сентября 2008

Можете ли вы написать тривиальную хранимую процедуру, которая каждый раз приводит к ошибкам / ошибкам, а затем использовать ее для тестирования?

...