パブリック コンストラクターを使用せずに OracleException をモック/フェイク/スタブでシールするにはどうすればよいですか?
-
02-07-2019 - |
質問
私のテストでは、(ストアド プロシージャの失敗により) OracleException がスローされたときに何が起こるかをテストする必要があります。Rhino モックをセットアップしようとしています
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 オブジェクトの新しいインスタンスを構築するのに問題がありますが、パブリック コンストラクターが存在しないというメッセージが表示され続けます。上記のすべてのアイデアを試してみましたが、null 参照例外が発生し続けます。
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);
テスト コードをデバッグすると、常に「ci」に NULL 値が返されます。
Oracle はこれを許可しないようにライブラリを変更しましたか?何が間違っているのでしょうか? NMock で使用する OracleException オブジェクトをインスタンス化するには何をする必要がありますか?
ちなみに、私はバージョン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 つの引数を取るリストの 2 番目のものでした。 int, string, string, string, int
. 。ILSpyでは次のようになっていましたので、5番目の引数には驚きました
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 } );
-デイブ
毎回失敗/エラーが発生する簡単なストアド プロシージャを作成し、それをテストに使用できますか?