11

約500の単体テストを含む.NETライブラリプロジェクトがあります。これらのテストはすべてVisualStudio2012で正常に実行されます。ただし、一部のテストはVisual Studio 2010で失敗します。これらの失敗したテストでは、Moqを使用してからいくつかの相互運用機能タイプをモックしMicrosoft.Office.Interop.Excelます。これらのモックされた相互運用タイプにアクセスしようとすると、テストはすぐに失敗します。

Error: Missing method 'instance class Microsoft.Office.Interop.Excel.Range [ExcelAddIn.Core] Microsoft.Office.Interop.Excel.ListRow::get_Range()' from class 'Castle.Proxies.ListRowProxy'.

この例外は、モックに適切なプロパティゲッターを設定するのを忘れたことを意味します。そうではありません:

_listRowMock.Setup(m => m.Range).Returns(_rangeMock.Object);

これで、Moqが相互運用タイプではうまく機能しない可能性があることが想像できます。しかし、私が最も困惑しているのは、これらのテストはVisual Studio 2012では正常に実行されますが、VisualStudio2010では失敗することです。

Visual Studioがコードの動作に影響を与えるのはなぜですか?

更新:2012年3月11日

わかりました、それで私はこれにそれを理解しました:

  • 私には2つのプロジェクトがあります。CoreおよびCore.UnitTest。Coreは実際のライブラリであり、Core.UnitTestはCoreライブラリの単体テストプロジェクトです。
  • どちらのプロジェクトも、埋め込み相互運用機能が有効になっているMicrosoft.Office.Interop.Excelを参照しています。
  • EITが有効になっているため、どちらのプロジェクトにもMicrosoft.Office.Interop.Excelライブラリの独自の「ビュー」が含まれています。ビューには、それぞれのプロジェクトで使用されるすべてのクラス、メソッド、およびプロパティが含まれます。
  • 両方のプロジェクトがMicrosoft.Office.Interop.Excelの異なるクラス、メソッド、およびプロパティを使用するため、両方のライブラリの埋め込みタイプは異なります。たとえば、CoreのListRowにはIndexプロパティとRangeプロパティがありますが、Core.UnitTestのListRowにはRangeプロパティしかありません。
  • どちらのタイプも異なり、共通のインターフェイスやスーパークラスを共有していませんが、同等です。これは、CLRがそれらを同じものとして扱い、アセンブリの境界を越えてこれらのタイプを使用できるようにすることを意味します。たとえば、Core.UnitTestのListRowのインスタンスは、コアライブラリのメソッドに渡されたときに正常に機能します。共有のRangeプロパティは機能しますが、欠落しているIndexプロパティは、アクセス時にMissingMethodExceptionをスローします。
  • 前述の動作は、モックされたタイプでも機能します。Mock [Excel.ListRow]のモックオブジェクトは、アセンブリの境界を越えるときに正常に機能します。
  • 残念ながら、前のポイントで説明した動作は、VisualStudio2012でアセンブリをビルドする場合にのみ機能します。Visual Studio 2010でアセンブリをビルドしてコードをデバッグすると、モックされたListRowインスタンスがコアプロジェクトのメソッドに渡されていることがわかります。インスタンスがアセンブリの境界を越えると、ListRowのすべてのメソッドとプロパティが実装を失い、MissingMethodExceptionsをスローします。
  • 楽しい部分として、私は実際に、両方の埋め込みタイプのListRowが整列されていることを確認することで、この問題を軽減することができました。たとえば、コンパイラが両方のプロジェクトでListRowの同じビューを作成するために、UnitTestプロジェクトでまったく同じメソッドとプロパティを使用していることを確認しました。これは、var dump=listRow.Indexのようなダミー行を追加することを意味します。コンパイラに埋め込みListRowタイプの同一のビューを作成させると、インスタンスはその実装を失うことなくアセンブリの境界を越えることができました。

ただし、まだ疑問が残ります。VisualStudio2010とVisualStudio 2012の動作にこの違いが生じる原因は何ですか?

更新:2012年9月11日

デモソリューションhttp ://temp-share.com/show/KdPf6066h

効果を実証するための小さなソリューションを作成しました。このソリューションは、ライブラリとUnitTestプロジェクトで構成されています。どちらも、EITが有効になっているMicrosoft.Office.Interop.Excel.Rangeを参照しています。テストはVS2012で正常に機能しますが、VS2010ではMissingMethodExceptionをスローします。テストでダミー行のコメントを解除すると、VS2010で機能するようになります。

最終更新:2012年12月29日

更新が遅れたことをお詫びします。同僚が解決策を見つけましたが、自分のマシンでそれを再現することができませんでした。その間に、当社はTFS2012に切り替えたので、これは私にとってもはやブロッキングの問題ではありません。私の同僚が行った2つの最も重要な結論は次のとおりです。

  • 「任意のCPU」プラットフォームのセマンティクスがVisualStudio2010からVisualStudio2012に変更されました。これにより、VS2010とVS2012のどちらを使用しているかに応じて、異なる.DLLが生成されます。
  • どちらのプロジェクトも、異なるバージョンのMicrosoft.Office.Interop.Excelを参照していました。

私は自分のプロジェクトをチェックし、参照を整理しましたが、違いはありませんでした。その後、VS2010とVS2012の両方でプラットフォームのさまざまなバリエーションを試しましたが、満足のいく結果を得ることができませんでした。ジェレミーの答えが最も役に立ったので、私はそれを受け入れます。皆様のご協力に感謝いたします。

4

4 に答える 4

6

編集: Visual Studio 2012で試して、.Net 4.0をターゲットにすると、COM参照ではなく.NetPIAのみを使用して機能します。同じソリューションはVS2010では機能しません。

VS2010はバージョンの10.0.30319.1をMicrosoft.VisualStudio.QualityTools.UnitTestFramework.dll'sロードし、VS2012はバージョンの11.0.50727.1をロードします。モジュールウィンドウで異なるバージョンを確認できます。


私はそれをVS2010で動作させることができました:

ここに画像の説明を入力してください

これが私の解決策ですhttp://temp-share.com/show/Pf3Ypip62みんなの便宜のために。すべてのMoqリファレンスが含まれています。私はExcel2007(つまり、v12)を使用しています。Office14への参照を調整してください。

Microsoft.Office.Interop.Excelテストするメソッドを持つプロジェクトは、.Net参照タブを介してPIAを使用する必要があります。

単体テストプロジェクトでは、Microsoft Excel 1X.0 Object Library[COM参照]タブ(ActiveX)を使用する必要があります。

紛らわしいのは、ソリューションエクスプローラーでは、どちらもMicrosoft.Office.Interop.Excelと呼ばれていることです。

回避方法がわからないもう1つの注意点があります。.Net3.5フレームワークを使用する必要があります。実際、.Net 4.0のすべてのプロジェクトでそれを行う方法を実行できないため、Microsoftが2012年に修正することを望んでいました。 。.Net3.5と4.0を対象とした混合プロジェクトの一部のソリューションは問題ありません。

これで多くの問題が発生しました。ここを参照してください。Excel.worksheetをモックするときに動的を使用しないようにするにはどうすればよいですか。 また、私が尋ねたこの質問も参照してください。モックオブジェクトには、Intellisenseに表示されるすべてのプロパティが含まれているわけではありません

とにかく、これがVS2010で機能させる方法です。2012年に解決されてうれしいです。

于 2012-11-11T03:44:57.700 に答える
3

これを再現しようとしましたが、VS2012でも動作しません。

「EmbedInteropTypes」を使用してプロジェクトをコンパイルすると、C#コンパイラは、アクセスしているメンバーのみを持つ内部型を生成します。実装は、実際にはIDispatchを使用してCOMオブジェクトのメソッドをidで呼び出すようです。

あなたの説明から、VS 2012のテストプロジェクトはプロパティにアクセスしないことを理解しています(それらをモックするためでも)が、テストは成功し、テストプロジェクトで生成されたタイプにこれらのメンバーがあります。

これが実際に発生していることである場合は、テスト.dllの内容を調べて、相互運用機能の種類がどのように生成されたかを確認してください。などのツールを使用できますildasm.exe

test .dllの相互運用機能タイプにすべてのメンバーが含まれている場合(テストでアクセスしないメンバーも含む)、これにより、VS2012での相互運用機能タイプの生成方法に違いがあることがわかります。

また、問題を再現する小さな最小限のVS 2012ソリューションを添付できる場合は、これを診断するのに大いに役立つ可能性があります。

于 2012-11-08T21:57:30.250 に答える
0

まず、VS2010でプロジェクトにライブラリを追加する際に、次のようなモックオブジェクトを作成したことを確認してください。

Mock<DocumentService> _mock = new Mock<DocumentService>();

また、.NET 4.0では、プライマリ相互運用機能アセンブリをアセンブリに埋め込むことができるため、アプリケーションと一緒に展開する必要はありません。VS2010でアセンブリの[プロパティ]タブを開き、[EmbedInteroptypes.mkae]が正しいことを確認してください。

そして、Excelをインスタンス化するために、Excel.Application xlapp = new Excel.Application();

それがうまくいくことを願っています。

于 2012-11-08T06:46:53.187 に答える
0

少なくともVS2015では、テスト対象のアセンブリに相互運用機能タイプを埋め込むことができましたが、テストプロジェクトのPIAアセンブリ参照で「Embed」をfalseに設定したため、これを再現できません。

于 2017-01-13T00:00:53.683 に答える