Как я могу имитировать/подделывать/заглушать запечатанное OracleException без открытого конструктора?

StackOverflow https://stackoverflow.com/questions/122215

Вопрос

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

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

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

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

public sealed class OracleException : DbException {
  private OracleException(string message, int code) { ...}
}
Это было полезно?

Решение

Похоже, что 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 });

Другие советы

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

Вот как это сделать:

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

Спасибо всем, кто помог, за вас проголосовали

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

Спасибо,

Чарли

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

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

new OracleException()

с

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

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

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

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

-Дэйв

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top