NUnitはアセンブリを見つけることができませんが、コンソールアプリは質問できます

NUnitはアセンブリを見つけることができませんが、コンソールアプリは質問できます

私はC#クラスでMatlab 関数から構築された .Net アセンブリ単純な C# コンソール アプリケーションからこの関数を問題なく呼び出すことができます。

ただし、NUnit から単体テストを実行しようとすると、次の例外が発生します。

ClassLibrary1.Tests.UnitTests.TestPerformOptimization: System.Reflection.TargetInvocationException: 呼び出しのターゲットによって例外がスローされました。 ----> System.Exception: .NET オブジェクトのマーシャリング エラー。 'メッセージ: アセンブリ 'ClassLibrary1、バージョン = 1.0.0.0、カルチャ = ニュートラル、PublicKeyToken = null' が見つかりません。 ソース: mscorlib ヘルプリンク: '

スタンドアロンの NUnit コンソール、ReSharper のテスト ランナーからクラスを呼び出そうとした場合、または Excel (Excel-DNA を使用) などから関数を呼び出そうとした場合、同じエラーが発生します。

コンパイルされた Matlab コンポーネントを呼び出すとき、実際には C# メソッド (MWObjectArray オブジェクト内) をラップして挿入します。コンパイルされた Matlab コンポーネントがこの挿入されたメソッドを呼び出そうとしたときに問題が発生していると思います。

私が見つけた唯一の回避策は、クラスのコピー (挿入されるメソッドを含む) を NUnit テスト ランナー、ReSharper テスト ランナー、または Excel と同じ場所に配置することです。ただし、このアプリケーションをユーザーのマシンにインストールする必要があるため、これは今後は実用的な解決策ではありません。同じ理由で、使用できないもう 1 つのオプションは、ファイルを %DEVPATH% にコピーすることです。

Matlab コンポーネントに、注入されたメソッド/クラスのアセンブリがどこにあるかを伝える方法はありますか?

サンプルプロジェクトのダウンロード

ダウンロード可能なサンプルプロジェクトがありますここ. zip ファイル内にある README.txt ファイルの指示に従ってください。

アップデート1

クラスを変更してコンストラクターに次のコードを含めることで、ユニット テストでアセンブリを認識できるようになりました。

AppDomain.CurrentDomain.AssemblyResolve +=
                 (sender, args) => typeof(OptimizationFunction).Assembly;

しかし、今度は次の例外が発生します。

例外: System.Reflection.TargetInvocationException: 呼び出しのターゲットによって例外がスローされました。 ---> System.Exception: .NET オブジェクトのマーシャリング エラー。 'メッセージ: ファイルまたはアセンブリ 'dotnetcli、バージョン = 1.0.5488.33915、カルチャ = ニュートラル、PublicKeyToken = da1231a838c93da4' またはその依存関係の 1 つを読み込めませんでした。厳密に名前が付けられたアセンブリが必要です。 (HRESULT からの例外: 0x80131044) ソース: mscorlib ヘルプリンク: ' at dotnetcli.throwNetExceptionID(BaseMsgID* msgId) at dotnetcli.DeployedDataConversion.GetMxArrayFromObject(Object data)
--- 内部例外スタック トレースの終了 --- at System.RuntimeMethodHandle.InvokeMethod(Object target、Object[] arguments、Signature sig、Boolean コンストラクター)

そのため、dotnetclli.dll の解決に問題が発生しています (以下の Fusion ログ/例外を参照)。私の知る限り、このファイルは C:\Program Files (x86)\MATLAB\MATLAB Runtime\v85\bin\win32 にのみ存在するはずです。

以下は Fusion Log からの抜粋です:

=== 事前バインド状態情報 ===

ログ: DisplayName = ClassLibrary1 (部分的) WRN: アセンブリ名: ClassLibrary1 | ドメイン ID: 1 WRN: アセンブリの表示名の一部のみが指定されると、部分的なバインドが発生します。 WRN: これにより、バインダーが間違ったアセンブリをロードする可能性があります。 WRN: アセンブリには、単純な名前、バージョン、カルチャ、および公開キー トークンで構成される、完全に指定されたテキスト ID を提供することをお勧めします。 > WRN: ホワイトペーパーを参照してくださいhttp://go.microsoft.com/fwlink/?LinkId=109270この問題の詳細情報と一般的な解決策については、こちらを参照してください。 ログ: Appbase = file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ ログ: Initial PrivatePath = NULL ログ: Dynamic Base = NULL ログ: Cache Base = NULL ログ: AppName = nunit-agent-x86.exe 呼び出しアセンブリ: (不明)。

=== ログ: このバインドは、既定の読み込みコンテキストで開始されます。ログ: アプリケーション構成ファイルの使用: C:\Insight\TFS\Asg\ConsoleApplication4\packages\NUnit.Runners.2.6.3\tools\nunit-agent-x86.exe.Config ログ: ホスト構成ファイルの使用: ログ: C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config のコンピューター構成ファイルの使用。ログ: 現時点では参照にポリシーが適用されていません (プライベート、カスタム、部分的、または場所ベースのアセンブリ バインド)。ログ: 新しい URL ファイルのダウンロードを試行しています: ///C:/XXXXX/ConsoleApplication4/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1.DLL。ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1/ClassLibrary1.DLL。 ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1/ClassLibrary1.DLL。 ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1/ClassLibrary1.DLL。 ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1.DLL。ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1/ClassLibrary1.DLL。 ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1.EXE。 ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/ClassLibrary1/ClassLibrary1.EXE。 ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1.EXE。ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/lib/ClassLibrary1/ClassLibrary1.EXE。 ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1.EXE。 ログ: 新しい URL ファイルのダウンロードを試行しています: file:///C:/XXXXX/ConsoleApplication1/packages/NUnit.Runners.2.6.3/tools/addins/ClassLibrary1/ClassLibrary1.EXE。 ログ: すべてのプローブ URL が試行されましたが、失敗しました。

WRN: アセンブリに対して部分的なバインディング情報が提供されました: コンソール アプリではこのアセンブリを解決できるのに、NUnit テストでは解決できないのはなぜですか?

アップデート2

Matlab に問い合わせたところ、次のような返答がありました。

私の知る限り、これはデシリアライズに関する .NET のデフォルトの動作です。クラスをデシリアライズするアプリケーションは、アセンブリを自身の現在のフォルダと GAC で検索しますが、見つからない場合は検索します。これは次の動作に似ています (これを読むときは MATLAB を Nunit に置き換えてください)

http://www.mathworks.com/matlabcentral/answers/101695-why-can-my-assembly-not-be-found-when-deserializing-a-net-object-in-matlab-7-10-r2010a

あなたの例は、MATLAB が関係する状況を表していません。MATLAB はクラスを APPDomain 間で送信します。あなたの例では、それは行われません。

Fuslogvw を使用してバインディングを確認します。アセンブリを見つけられないのは MATLAB ではなく、依存関係を解決できない呼び出しアプリケーション (この場合は nunit-agent-x86.exe) であることがわかります。

ベストアンサー1

ConsoleApplication4 のコンパイルによって必要なすべてのファイルが生成され、実行可能ファイルの他に配置されていることを確認します (必要なアセンブリ DLL、ランタイム DLL、.config ファイルなど)。

これが起こることを確認したら、NUnit を --no-shadow-copy コマンドライン スイッチで起動するか、GUI ツールから構成パラメータとして設定します。Bush が言ったように、NUnit は通常、テスト対象のファイルを別のディレクトリにコピーするため、重要なファイルが残ってしまうことがあります。

Matlab によって作成されたクラスに何らかの特定のランタイムが必要な場合は、テストを実行しているコンピューターや Excel/ReSharper を使用しているコンピューターにそのランタイムが正しくインストールされていることを確認してください。

このレベルでは、アセンブリ解決プロセスをいじろうとはしません。リンクした記事の内容を要約してください。有料なので、NUnit のシャドウ コピーなし設定を試してください。

おすすめ記事