测试c#中的两个依赖类

本文关键字:两个 依赖 测试 | 更新日期: 2023-09-27 18:02:05

我想解决的问题是,如何在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
    }
}

当向集合中添加项时,将生成一个新的Id并将其分配给CustomItem。自动计数机制也应该包含在其他方法中,例如Remove(),但是对于这个问题,我只留下Add方法。

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

tl;博士

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

测试c#中的两个依赖类

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

开始时,我不会使用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; }
    }
}
一旦你掌握了这个技巧,你也可以使用Moq用更少的样板代码创建更简洁的测试。在这种情况下,也可以使用NUnit parameterizedtest用例。

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

在这里阅读我的回答,以获得有关同一主题的更多信息。. NET (WebForm)应用程序有良好的单元测试(CodePlex或任何地方)?

我使用FakeItEasy作为mock/fake-framework,但我猜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
    }
}

编辑

删除未测试的moq -示例,似乎不工作。

模拟没有被修改,这一点是正确的。但是您应该能够在调用add方法之后验证mock,如下所示:

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

记住在调用Add之前在Items属性中设置一些东西。当请求Count()时,该东西应该返回42。