Как я могу имитировать/подделывать/заглушать запечатанное OracleException без открытого конструктора?
-
02-07-2019 - |
Вопрос
В моих тестах мне нужно проверить, что происходит, когда генерируется исключение 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 конструкторов
Мне нужен был второй в списке, который принимал 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 } );
-Дэйв
Можете ли вы написать тривиальную хранимую процедуру, которая каждый раз дает сбой/ошибку, а затем использовать ее для тестирования?