Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C语言中测试两个依赖类#_C#_Unit Testing_Dependencies_Moq - Fatal编程技术网

C# 在C语言中测试两个依赖类#

C# 在C语言中测试两个依赖类#,c#,unit-testing,dependencies,moq,C#,Unit Testing,Dependencies,Moq,我想解决的问题是,如何在C#中测试两个依赖类。对于测试,我使用NUnit和Moq 假设我有一个自定义集合,可以自动计算其项目。集合中的值必须保持其原始顺序,这就是它必须自动计算的原因。以下代码显示了上述类的最简单示例: public interface ICustomItem { int Id { get; set; } ICustomCollection<ICustomItem> ParentCollection { get; set; } } public in

我想解决的问题是,如何在C#中测试两个依赖类。对于测试,我使用NUnit和Moq

假设我有一个自定义集合,可以自动计算其项目。集合中的值必须保持其原始顺序,这就是它必须自动计算的原因。以下代码显示了上述类的最简单示例:

public interface ICustomItem
{
    int Id { get; set; }
    ICustomCollection<ICustomItem> ParentCollection { get; set; }
}

public interface ICustomCollection<T> where T : ICustomItem
{
    IEnumerable<T> Items { get; set; }
    void Add(T t);
    // And more of course...
}

public class CustomCollection<T> : ICustomCollection<T> where T : ICustomItem
{
    public IEnumerable<T> Items { get; set; }

    public void Add(T t)
    {
        // Some logic here...
        t.Id = Items.Count(); // Generate Id
    }
}
公共接口ICustomItem
{
int Id{get;set;}
ICustomCollection ParentCollection{get;set;}
}
公共接口ICustomCollection,其中T:ICustomItem
{
IEnumerable Items{get;set;}
无效添加(T);
//当然还有更多。。。
}
公共类CustomCollection:ICustomCollection,其中T:ICustomItem
{
公共IEnumerable项{get;set;}
公共无效添加(T)
{
//这里有些逻辑。。。
t、 Id=Items.Count();//生成Id
}
}
将项目添加到集合时,将生成一个新Id并将其分配给CustomItem。自动计算机制也应该包括在其他方法中,例如Remove(),但对于这个问题,我只留下Add方法

问题是,如何测试自动编码是否正确工作?当mock作为param传递时,它不会在类内部修改。我是否应该使用为tests CustomItem类创建的简单实例测试该类

tl;dr


换句话说,我希望能够在类中修改mock。

事实上,mock没有被修改。但是,您应该能够在调用add方法后验证模拟,如下所示:

mock.VerifySet(x => x.Id = 42);

在调用Add之前,请记住在Items属性中设置一些内容。当询问Count()时,某物应该返回42。这也可能是一个模拟。

尝试在测试中使用该类,就像在生产代码中使用它一样。这将为您提供最有用的测试,因为您可以自由重构类内部的代码,而无需中断甚至更改测试。该测试还将作为如何使用该类的示例

首先,我不会使用Moq,而是使用一个简短的
MockCustomItem
类,您只为测试而实现它

然后使用add一些值并断言结果是您所期望的。养成在每个测试中只使用一个断言的习惯,如下所示

[TestFixture]
public class GivenCustomCollectionWithTwoElements
{
    private CustomCollection<MockCustomItem> _customCollection;

    [SetUp]
    public void SetUp()
    {
        _customCollection = new CustomCollection<MockCustomItem>();

        _customCollection.Add(new MockCustomItem());
        _customCollection.Add(new MockCustomItem()); 
    }

    [Test]
    public void CheckLength()
    {
        Assert.That(_customCollection.Items, Is.EqualTo(2));
    }

    [Test]
    public void CheckFirstItemId()
    {
        Assert.That(_customCollection.Items.ElementAt(0).Id, Is.EqualTo(0));
    }

    [Test]
    public void CheckSecondItemId()
    {
        Assert.That(_customCollection.Items.ElementAt(1).Id, Is.EqualTo(1));
    }

    private class MockCustomItem : ICustomItem
    {
        public int Id { get; set; }
        public ICustomCollection<ICustomItem> ParentCollection { get; set; }
    }

}
[TestFixture]
具有两个元素的public类givencustomcollection
{
私人CustomCollection\u CustomCollection;
[设置]
公共作废设置()
{
_customCollection=新建customCollection();
_添加(新MockCustomItem());
_添加(新MockCustomItem());
}
[测试]
公共void CheckLength()
{
断言(_customCollection.Items,Is.EqualTo(2));
}
[测试]
public void CheckFirstItemId()
{
Assert.That(_customCollection.Items.ElementAt(0.Id,Is.EqualTo(0));
}
[测试]
public void CheckSecondItemId()
{
Assert.That(_customCollection.Items.ElementAt(1.Id,Is.EqualTo(1));
}
私有类MockCustomItem:ICustomItem
{
公共int Id{get;set;}
公共ICustomCollection父集合{get;set;}
}
}

一旦掌握了窍门,还可以使用Moq创建更简洁的测试,使用更少的样板代码。在这种情况下,也可以使用NUnit参数化测试用例。

在单元测试中,您只能测试当前正在测试的单元。所以我想说,你应该模拟/伪造ICustomItem并发送它,然后查看伪造的对象是否获得了你期望的Id

请阅读我的答案,了解关于同一主题的更多信息

我使用FakeiTesy作为模拟/伪框架,但我想moq看起来很相似,下面是我的代码

[TestFixture]
public class CustomCollectionTests{

    [Test]
    public void Add_AddTwoItems_ItemsGetsConsecutiveIds() {
        var customItem1 = A.Fake<ICustomItem>();
        var customItem2 = A.Fake<ICustomItem>();
        var cutomCollection = new CustomCollection<ICustomItem>();
        cutomCollection.Add(customItem1);
        cutomCollection.Add(customItem2);
        Assert.AreEqual(1, customItem1.Id);
        Assert.AreEqual(2, customItem2.Id);
    }
}


public interface ICustomItem {
    int Id { get; set; }
}

public interface ICustomCollection<T> where T : ICustomItem {
    void Add(T t);
}

public class CustomCollection<T> : ICustomCollection<T> where T : ICustomItem {
    public List<T> innerList = new List<T>();

    public void Add(T t) {
        // Some logic here...
        innerList.Add(t);
        t.Id = innerList.Count(); // Generate Id
    }
}
[TestFixture]
公共类CustomCollectionTests{
[测试]
public void Add_addtwooitems_ItemsGetsConsecutiveIds(){
var customItem1=A.Fake();
var customItem2=A.Fake();
var cutomCollection=new CustomCollection();
添加(customItem1);
cutomCollection.Add(customItem2);
aresequal(1,customItem1.Id);
aresequal(2,customItem2.Id);
}
}
公共接口ICustomItem{
int Id{get;set;}
}
公共接口ICustomCollection,其中T:ICustomItem{
无效添加(T);
}
公共类CustomCollection:ICustomCollection,其中T:ICustomItem{
public List innerList=新列表();
公共无效添加(T){
//这里有些逻辑。。。
innerList.Add(t);
t、 Id=innerList.Count();//生成Id
}
}
编辑


删除了似乎不起作用的未测试MOQ示例。

为什么不能使用模拟?您可以使用Id属性上的SetupSet创建mock。@msergey:但是如何设置mock Id setter来检查它是否在Add()方法中被正确修改?你能提供一个例子吗?你能在Add()之后检查它吗?因此,您将项添加到集合中,并在运行add之后检查Id设置是否正确。您的Moq代码是错误的:首先,您必须使用customItem#.Object,其次,您不能修改一个mock inside add()方法。啊,Fakeitesy似乎可以更轻松地处理此问题;)我再次删除了MOQ代码示例。请查看此链接,其中Osherove解释了为什么每个测试一个断言很重要:我可能会将Id的生成移动到另一个类,而不是将其包含在集合中。如果你阅读单一责任原则,你会发现一个班级应该有一个责任。你的收藏既储存了ICustomItems,又对它们进行了修改。哇,我刚刚注意到维斯蒂奇和文特1是两个不同的人;)我以为我一直在和同一个人说话。。。我的错。对不起;)我所说的一切仍然适用,尽管很抱歉。刚刚意识到您正在IEnumerable上使用Count()扩展方法,而不是List和其他集合类型上可用的Count属性。Count()是一个s