2

単体テストを作成しようとしています。クラス Position は、サードパーティ ライブラリに実装されています。しかし、単体テストでは、Size プロパティを特定の値に設定する必要があります。

public class Position
{
    private double _size;

    private double Size
    {
        get
        {
            return _size;
        }

        internal set
        {
            _size = value;
        }
    }
}

この投稿を読みました:読み取り専用メンバーを含むインターフェイスの単体テスト スタブを作成するにはどうすればよいですか? しかし、それを機能させる方法がわかりませんでした。

これはテスト対象のクラスです (単純化された例です)。メソッドのpos引数は次CalcPositionMetric()の型でなければなりませんPosition:

public class PositionMetrics
{
    public PositionMetrics()
    {}

    public double CalcPositionMetric(Position pos)
    {
        return 2 * pos.Size;
    }
}

これが私の単体テストの一部です:

using NUnit.Framework;
using NMock;

[TestFixture]
public class PositionUnitTests
{
    [Test]
    public void TestPosition()
    {
        Mock<Position> tmpPosMock   = mFactory.CreateMock<Position>();
        tmpPosMock.Expects.One.GetProperty(v => v.Size).WillReturn(7); /* !!! Exception !!! System.ArgumentException : mock object position has a getter for property Size, but it is not virtual or abstract */

        /* Execute Test with  tmpPositions*/
        PositionMetrics pm = new PositionMetrics();
        double result      = pm.CalcPositionMetric(tmpPosMock.MockObject)
        Assert.AreEqual(14, result);
    }
}

しかし、ご覧のとおり、例外が発生します。誰かがこの問題を解決するのを手伝ってくれますか? 他のソリューションも大歓迎です!

乾杯コンスタンチン

4

1 に答える 1

2

更新された質問に対する新しい回答そのために、ある種のプロキシインターフェイスを導入することをお勧めします。以下のコードを参照してください。

interface IPosition { 
    int Size { get; }
}
class Position { //in 3rd party lib
    public int Size {
        get { return 5; }
    }
}
class RealPosition : IPosition { //use this as your real object instead of using Position directly
    private Position position;
    public RealPosition(Position position) {
        this.position = position;
    }
    public int Size {
        get { return position.Size; }
    }
}
class MockPosition : IPosition { //use this for testing
    public int Size{ get; set; }
}
public class Program {
    static void Main(string[] args) {
        var pos = new MockPosition { Size = 7 };
        Console.WriteLine(Calc(pos));    //prints 14
        Console.ReadLine();
    }
    static int Calc(IPosition pos) { //change your method signature to work with interface
        return pos.Size * 2;
    }       
}

古い答えクラスがsealedそうでない場合、モックライブラリは必要ありません。new次のように、必要なプロパティに修飾子を使用するだけです。

class Position {
    public int Size { get { return 5; } }
}

class MockPosition : Position {
    public new int Size { get; set; }
}
....
var mock= new MockPosition();
mock.Size = 7;

これらのアイテムをある種のリストで使用するには、次のようにキャストする必要があります。

var items = new List<Position>();
for (int i = 0; i < 5; i++) {
      items.Add(new MockPosition { Size = i });
}
foreach (var item in items.Cast<MockPosition>()) {
       Console.Write("{0}\t", item.Size); //prints 0 1 2 3 4
}

それが封印されていて、プロパティが仮想でない場合は、他のいくつかの手法を使用する必要がありますMoq(使用していると思います)。

于 2016-01-25T12:46:14.500 に答える