0

属性の値を含むメモリ位置に IntPtr を返すネイティブ ライブラリを使用しています。属性の型が何であるかを知っており、ポインターが指すメモリから値をマーシャリングする (IntPtr と属性の型を取得する) メソッドがあります。このメソッドは、Marshal.ReadInt32 を呼び出すか、一連のバイトを読み取って double に変換するか、Marshal.PtrToStringUni などを使用して文字列を読み取ります。このメソッドの単体テストをいくつか書きたいのですが、どうすればよいかわかりません。メソッドに渡す IntPtr の作成について。NUnit を使用していて、モック フレームワークを使用できません。

4

3 に答える 3

1

IntPtrを使用して値を初期化できるMarshal.Copy()のさまざまなオーバーロードを確認してください。

于 2008-10-22T09:53:32.930 に答える
0

私が正しく理解していれば、IntPtrを指定して、逆シリアル化のロジックを単体テストする必要があります。
その場合は、シリアル化された出力のさまざまな組み合わせのコピーを用意して、それぞれの一意のパスをテストするだけです。テストごとに、シリアル化された可能性のあるエンティティへのIntPtrを取得し、メソッドを呼び出して、期待される結果を確認します。

メモリ内の領域へのポインタを取得するようなもの。シリアル化された出力を文字列で保持し、そこからIntptrを取得します。GCHandleは、ここで必要なもののように見えます。(ただし、これを試したことはありません) http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.tointptr.aspx

于 2008-10-22T09:49:34.277 に答える
0

私があなたの質問を読んだことで、あなたが求めているのは次のようだと思います。

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を使用しているので、そうではないと思います。

于 2008-10-22T10:44:12.857 に答える