Pergunta

Nos meus testes, preciso testar o que acontece quando uma OracleException é lançada (devido a uma falha no procedimento armazenado). Estou tentando configurar zombares de rinocerontes para

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

Por qualquer motivo, no entanto, o OracleException parece estar selado sem construtor público. O que posso fazer para testar isso?

Editar: Aqui está exatamente o que estou tentando instanciar:

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

Solução

Parece que o Oracle alterou seus construtores em versões posteriores; portanto, a solução acima não funcionará.

Se você deseja definir apenas o código de erro, o seguinte fará o truque para 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 });

Outras dicas

Para o acesso de dados gerenciados da Oracle (v 4.121.1.0), o construtor mudou novamente

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

Aqui está como você faz isso:

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

Graças a tudo o que ajudou, você foi votado

Estou usando o cliente Oracle.DataAccess.Client Data Provider. Estou tendo problemas para construir uma nova instância de um objeto OracleException, mas continua me dizendo que não há construtores públicos. Tentei todas as idéias mostradas acima e continuei recebendo uma exceção de referência nula.

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

Ao depurar o código de teste, sempre recebo um valor nulo para 'CI'.

O Oracle mudou a biblioteca para não permitir isso? O que estou fazendo de errado e o que preciso fazer para instanciar um objeto OracleException para usar com o NMOCK?

A propósito, estou usando a biblioteca do cliente para a versão 10G.

Obrigado,

Charlie

Use a reflexão para instanciar o OracleException. Ver esta postagem do blog

Use a reflexão para instanciar o objeto OracleException? Substituir

new OracleException()

com

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

Você sempre pode obter todos os construtores como este

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

Por Oracle.DataAccess 4.112.3.0 Isso retornou 7 construtores

enter image description here

O que eu queria era o segundo da lista que levou 5 argumentos, int, string, string, string, int. Fiquei surpreso com o quinto argumento porque em Ilspy parecia assim

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

Então, para obter o construtor que eu queria, acabei usando

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

Boa solução George.Isso também funciona para SqlException também:

        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

Você pode escrever um trivial procedimento armazenado que falha/erros de cada vez, em seguida, usar o que testar?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top