C#使用内部属性设置器模拟类

C#使用内部属性设置器模拟类,c#,mocking,nmock,C#,Mocking,Nmock,我正在尝试构建一个单元测试。 类位置在第三方库中实现。但是对于我的单元测试,我需要将Size属性设置为一个特定的值 公共类职位 { 私人双倍大小; 私人双码 { 得到 { 返回大小; } 内部集 { _大小=值; } } } 我读了这篇文章: 但我想不出如何让它为我工作 这是正在测试的类(只是一个简化的示例)。CalcPositionMetric()方法中的pos参数必须是Position类型: 下面是我的单元测试的一部分: 使用NUnit.Framework; 使用NMock; [测试夹具

我正在尝试构建一个单元测试。 类位置在第三方库中实现。但是对于我的单元测试,我需要将Size属性设置为一个特定的值

公共类职位
{
私人双倍大小;
私人双码
{
得到
{
返回大小;
}
内部集
{
_大小=值;
}
}
}
我读了这篇文章: 但我想不出如何让它为我工作

这是正在测试的类(只是一个简化的示例)。
CalcPositionMetric()
方法中的
pos
参数必须是
Position
类型:

下面是我的单元测试的一部分:

使用NUnit.Framework;
使用NMock;
[测试夹具]
公共类单元测试
{
[测试]
public void TestPosition()
{
Mock tmpPosMock=mFactory.CreateMock();
tmpPosMock.Expects.One.GetProperty(v=>v.Size).WillReturn(7);/*!!!Exception!!!System.ArgumentException:mock对象位置具有属性大小的getter,但它不是虚拟的或抽象的*/
/*使用tmpositions执行测试*/
PositionMetrics pm=新的PositionMetrics();
双重结果=pm.CalcPositionMetric(tmpPosMock.MockObject)
断言。结果相等(14,结果);
}
}
但正如你所看到的,我有一个例外。有人能帮我解决这个问题吗?任何其他解决方案也欢迎

干杯
Konstantin

更新问题的新答案我建议您为此引入某种代理接口。请参阅下面的代码:

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;
    }       
}
旧答案如果类未密封则不需要任何模拟库。只需对所需的属性使用
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
}
要在某种列表中使用这些项,您必须按如下方式对其进行强制转换:

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
}
var items=newlist();
对于(int i=0;i<5;i++){
添加(新的MockPosition{Size=i});
}
foreach(items.Cast()中的var item){
Console.Write(“{0}\t”,item.Size);//打印0 1 2 3 4
}

如果它是密封的,并且该属性不是虚拟的,那么您将不得不使用其他一些技术,
Moq
(我猜您正在使用)不允许这样做

您是否在程序集中有
[assembly:InternalsVisibleTo(“My.Tests.Project”)]
位置
Position
类位于第三方库中。它回答了你的问题吗?是的,谢谢,这让事情变得更清楚了。谢谢你的回答。但它不能起作用。我试过了。我的测试将
列表
作为参数。创建列表时,我执行以下操作
tmpositions.Add(mock)Size
值仍然为0。我刚刚更新了问题描述。如您所见,我不能使用
MockPosition
,因为方法
CalcPositionMetric()
需要类型为
Position
的参数。我只能将此解决方案用于测试。但是,我需要更改代码才能正常使用。这是我想要避免的事情。似乎是个好主意!我稍后会尝试一下,并让你知道这是否对我有效。目前我看不出有什么理由它不起作用。