属性の値を含むメモリ位置に IntPtr を返すネイティブ ライブラリを使用しています。属性の型が何であるかを知っており、ポインターが指すメモリから値をマーシャリングする (IntPtr と属性の型を取得する) メソッドがあります。このメソッドは、Marshal.ReadInt32 を呼び出すか、一連のバイトを読み取って double に変換するか、Marshal.PtrToStringUni などを使用して文字列を読み取ります。このメソッドの単体テストをいくつか書きたいのですが、どうすればよいかわかりません。メソッドに渡す IntPtr の作成について。NUnit を使用していて、モック フレームワークを使用できません。
3 に答える
IntPtrを使用して値を初期化できるMarshal.Copy()のさまざまなオーバーロードを確認してください。
私が正しく理解していれば、IntPtrを指定して、逆シリアル化のロジックを単体テストする必要があります。
その場合は、シリアル化された出力のさまざまな組み合わせのコピーを用意して、それぞれの一意のパスをテストするだけです。テストごとに、シリアル化された可能性のあるエンティティへのIntPtrを取得し、メソッドを呼び出して、期待される結果を確認します。
メモリ内の領域へのポインタを取得するようなもの。シリアル化された出力を文字列で保持し、そこからIntptrを取得します。GCHandleは、ここで必要なもののように見えます。(ただし、これを試したことはありません) http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.tointptr.aspx
私があなたの質問を読んだことで、あなたが求めているのは次のようだと思います。
IntPtrをdoubleまたはunicode文字列に返すネイティブ呼び出しをモックする関数を作成して、そのIntPtrをテストする関数に渡すにはどうすればよいですか?
このようなものが役立つかもしれません:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
private static double myDouble = 3.14;
private static unsafe void TestPtrToDouble()
{
fixed(double* pDouble = &myDouble)
{
IntPtr intp = new IntPtr(pDouble);
double[] copy = new double[1];
Marshal.Copy(intp, copy, 0, 1);
Debug.Assert(copy[0] == myDouble);
}
}
private static char[] myString = { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'm', 'y', ' ', 's', 't', 'r', 'i', 'n', 'g' };
private static unsafe void TestPtrToUnicodeString()
{
fixed (char* pChar = &myString[0])
{
IntPtr intp = new IntPtr(pChar);
string copy = Marshal.PtrToStringUni(intp);
Debug.Assert(copy == "This is my string");
}
}
static void Main(string[] args)
{
TestPtrToUnicodeString();
TestPtrToDouble();
}
}
}
非常に注意しなければならないのは、関数から作成された模擬IntPtrを返すことができないということです。つまり、P / Invoke呼び出しのモックバージョンを作成して、機能することを期待することはできません。
.Netランタイムは、管理対象オブジェクトをメモリ内で移動します(ガベージコレクションプロセスの一部)。このfixed
ステートメントは、アドレスを取得するメンバー/オブジェクトに対してこれが発生するのを防ぎます。しかし、ブロックの寿命の間だけ。関数から戻るとブロックが終了するため、戻った後はポインタ値が無効になる可能性があります。つまり、IntPtrが、マーシャリングするデータを含まなくなったメモリを参照している可能性があります。
安全でないコードと修正されたステートメントに関するMSDNドキュメントを確認してください。しかし、私がここで得たものは、マーシャリングコードのNUnitテストを構築するための正しい方向にあなたを送るはずです。
また、このコードをコンパイルするには、/unsafeコンパイラオプションが必要であることに注意してください。安全でないアセンブリをサポートしていない環境でアセンブリを実行する必要がある場合は、別のアセンブリにテストコードを含める必要があります。しかし、すでにP / Invokeを使用しているので、そうではないと思います。