C# 使用moq验证列表

C# 使用moq验证列表,c#,.net,unit-testing,mocking,moq,C#,.net,Unit Testing,Mocking,Moq,给定调用代码 List<Person> loginStaff = new List<Person>(); loginStaff.add(new Person{FirstName = "John", LastName = "Doe"}); this._iViewLoginPanel.Staff = loginStaff; List loginStaff=new List(); 添加(新人{FirstName=“John”,LastName=“Doe”}); 这._i

给定调用代码

List<Person> loginStaff = new List<Person>(); 

loginStaff.add(new Person{FirstName = "John", LastName = "Doe"});

this._iViewLoginPanel.Staff = loginStaff;
List loginStaff=new List();
添加(新人{FirstName=“John”,LastName=“Doe”});
这._iViewLoginPanel.Staff=loginStaff;
验证是否存在名为john doe的人员以及是否至少设置了一名人员的语法是什么?目前,我所看到的所有示例都非常基本,仅使用It.IsAny或Staff=一些基本类型,但没有一个实际验证列表等复杂类型中的数据

我的断言看起来像

this._mockViewLoginPanel.VerifySet(x=> x.Staff = It.IsAny<List<Person>>());
this.\u mockViewLoginPanel.VerifySet(x=>x.Staff=It.IsAny());
它只检查给定给setter的类型,而不检查列表本身中的大小或项目。我尝试过这样做:

        this._mockViewLoginPanel.VerifySet(
           x =>
           {
               List<string> expectedStaffs = new List<string>{"John Doe", "Joe Blow", "A A", "Blah"};
               foreach (Person staff in x.Staff)
               {
                   if (!expectedStaffs.Contains(staff.FirstName + " " + staff.LastName))
                       return false;
               }
               return true;
           });
this.\u mockViewLoginPanel.VerifySet(
x=>
{
List ExpectedStaff=新列表{“John Doe”、“Joe Blow”、“A A”、“Blah”};
foreach(x.staff中的人员)
{
如果(!expectedStaff.Contains(staff.FirstName+“”+staff.LastName))
返回false;
}
返回true;
});
但这告诉我lambda语句体不能转换为表达式树。 然后我想到将语句体放入函数并运行它,但在运行时我得到:

System.ArgumentException:表达式不是属性设置程序调用

更新: 根据使用assert的前两个答案,我尝试了该方法,但发现即使将Staff设置为非null列表,它在debug中仍然显示为null。这就是完整测试的外观

[TestMethod]
public void When_The_Presenter_Is_Created_Then_All_CP_Staff_Is_Added_To_Dropdown()
{
    this._mockViewLoginPanel = new Mock<IViewLoginPanel>();

    PresenterLoginPanel target = new PresenterLoginPanel(this._mockViewLoginPanel.Object);

    this._mockViewLoginPanel
        .VerifySet(x => x.Staff = It.IsAny<List<Person>>());

    Assert.AreEqual(5, this._mockViewLoginPanel.Object.Staff.Count);
}
[TestMethod]
public void当创建演示者时,然后将所有CP人员添加到下拉列表()中
{
这是。_mockViewLoginPanel=new Mock();
PresenterLoginPanel目标=新PresenterLoginPanel(this.\u mockViewLoginPanel.Object);
这是.\u mockViewLoginPanel
.VerifySet(x=>x.Staff=It.IsAny());
AreEqual(5,this.\u mockViewLoginPanel.Object.Staff.Count);
}
在PresenterLoginPanel的构造函数中的某个地方

public PresenterLoginPanel
{
    private IViewLoginPanel _iViewLoginPanel;

    public PresenterLoginPanel(IViewLoginPanel panel) 
    { 
        this._iViewLoginPanel = panel;
        SomeFunction();
    }

    SomeFunction() {
        List<Person> loginStaff = new List<Person>(); 

        loginStaff.add(new Person{FirstName = "John", LastName = "Doe"});

        this._iViewLoginPanel.Staff = loginStaff;
    }
}
public PresenterLoginPanel
{
私人IViewLoginPanel_IViewLoginPanel;
公共PresenterLoginPanel(IViewLoginPanel面板)
{ 
此._iViewLoginPanel=面板;
SomeFunction();
}
SomeFunction(){
List loginStaff=新列表();
添加(新人{FirstName=“John”,LastName=“Doe”});
这._iViewLoginPanel.Staff=loginStaff;
}
}

当我调试到下一行时,
this.\u iViewLoginPanel.Staff
为null,这是导致断言中出现null异常的原因。

您可以使用NUnit方法来断言mock对象的内容,而不是使用mock的方法

将列表分配给对象并验证其已设置后,使用断言检查细节,例如项目计数以及第一个对象是否与您期望的内容匹配

Assert.That(this._mockViewLoginPanel.Object.Staff.Length, Is.EqualTo(1));
Assert.That(this._mockViewLoginPanel.Object.Staff[0], Is.Not.Null);
Assert.That(this._mockViewLoginPanel.Object.Staff[0], Is.EqualTo(loginStaff[0]));
编辑

经过进一步调查,这归结为模仿行为。属性
Staff
Person
设置不正确

要设置它们,请将模拟创建更改为:

var _mockViewLoginPanel = new Mock<IViewLoginPanel>(MockBehavior.Strict);
_mockViewLoginPanel.SetupAllProperties();
var\u mockViewLoginPanel=newmock(MockBehavior.Strict);
_mockViewLoginPanel.SetupAllProperties();
演示的完整代码清单如下:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public interface IViewLoginPanel
{
    IList<Person> Staff { get; set; }
}

public class PresenterLoginPanel {

    private IViewLoginPanel _iViewLoginPanel;

    public PresenterLoginPanel(IViewLoginPanel panel) 
    { 
        _iViewLoginPanel = panel;
        SomeFunction();
    }

    public void SomeFunction() 
    {
        List<Person> loginStaff = new List<Person>(); 

        loginStaff.Add(new Person{FirstName = "John", LastName = "Doe"});

        _iViewLoginPanel.Staff = loginStaff;
    }

    public IViewLoginPanel ViewLoginPanel
    {
        get { return _iViewLoginPanel; }
    }
}

[TestFixture]
public class PresenterLoginPanelTests
{
    [Test]
    public void When_The_Presenter_Is_Created_Then_All_CP_Staff_Is_Added_To_Dropdown()
    {
        var _mockViewLoginPanel = new Mock<IViewLoginPanel>(MockBehavior.Strict);
        _mockViewLoginPanel.SetupAllProperties();

        PresenterLoginPanel target = new PresenterLoginPanel(_mockViewLoginPanel.Object);

        _mockViewLoginPanel.VerifySet(x => x.Staff = It.IsAny<List<Person>>());

        Assert.AreEqual(5, _mockViewLoginPanel.Object.Staff.Count);
    }

}
公共类人物
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
公共接口IViewLoginPanel
{
IList Staff{get;set;}
}
公共类PresenterLoginPanel{
私人IViewLoginPanel_IViewLoginPanel;
公共PresenterLoginPanel(IViewLoginPanel面板)
{ 
_iViewLoginPanel=面板;
SomeFunction();
}
公共函数()
{
List loginStaff=新列表();
添加(新人{FirstName=“John”,LastName=“Doe”});
_iViewLoginPanel.Staff=loginStaff;
}
公共IViewLoginPanel视图LoginPanel
{
获取{return\u iViewLoginPanel;}
}
}
[测试夹具]
公共类PresenterLoginPanelTests
{
[测试]
public void当创建演示者时,然后将所有CP人员添加到下拉列表()中
{
var\u mockViewLoginPanel=新的Mock(MockBehavior.Strict);
_mockViewLoginPanel.SetupAllProperties();
PresenterLoginPanel目标=新PresenterLoginPanel(_mockViewLoginPanel.Object);
_mockViewLoginPanel.VerifySet(x=>x.Staff=It.IsAny());
AreEqual(5,_mockViewLoginPanel.Object.Staff.Count);
}
}

这将检查人员计数是否应大于0,是否至少有一个项不为空,是否至少有一个项的名字等于Joe。如果要比较对象,必须添加比较器

Assert.AreNotEqual(this._mockViewLoginPanel.Object.Staff.Count, 0);
Assert.AreNotEqual(this._mockViewLoginPanel.Object.Staff.All(x => x == null), true);
Assert.AreEqual(this._mockViewLoginPanel.Object.Staff.Any(x => x.FirstName == "Joe"), true);

使用Moq本身可以很容易地实现这一点(当您还没有对预期结果对象的引用时)-只需使用
It.Is(…)
方法:

_mockViewLoginPanel.VerifySet(x => x.Staff = It.Is<List<Person>>(staff => staff.Count == 5));
_mockViewLoginPanel.VerifySet(x => x.Staff = It.Is<List<Person>>(staff => staff[0].FirstName == "John"));
\u mockViewLoginPanel.VerifySet(x=>x.Staff=It.Is(Staff=>Staff.Count==5));
_mockViewLoginPanel.VerifySet(x=>x.Staff=It.Is(Staff=>Staff[0].FirstName==“John”);

facepalms当然,我太专注于学习moq,而对库存单元测试关注不够:)事实上,我接受得太快了,当我使用你的代码时,它给了我一个对象空引用,因为Staff属性没有保存。(我调试以确保它被设置,但设置之后,值仍然为空)我注意到您有
\u iViewLoginPanel
\u mockViewLoginPanel
<代码>工作人员正在
\u iViewLoginPanel
上设置,而
断言
正在
\u mockViewLoginPanel
上执行。我第一次错过了这个。它们应该是同一个对象吗?我更新了我的问题的更多细节,基本上mockViewLoginPanel是