如何编写nUnit/Moq来测试通用扩展方法?

Blu*_*ppy 4 c# tdd nunit moq

我有以下通用扩展方法从ObjectContext中删除所有EntityObjects

public static void DeleleAllObjects<TEntity>(this ObjectContext context)
        where TEntity : EntityObject
    {
        var objectSet = context.CreateObjectSet<TEntity>();
        objectSet.ToList().ForEach(e => objectSet.DeleteObject(e));
    }
Run Code Online (Sandbox Code Playgroud)

我是TDD并且使用nUnit/Moq的新手......但是我不知道在哪里为这个方法编写测试?

Pab*_*meo 5

我希望这有帮助:

[TestFixture]
public class ExtensionTest
{
    public class FakeEntity : EntityObject
    {

    }

    [Test]
    public void DeleteAllObjects()
    {
        //arrange
        var objectsToDelete = new List<FakeEntity>
            {
                new FakeEntity(),
                new FakeEntity()
            };
        var mockContext = new Mock<ObjectContext>();
        var mockObjectSet = new Mock<ObjectSet<FakeEntity>>();
        mockObjectSet.Setup(x => x.ToList()).Returns(objectsToDelete);
        mockContext.Setup(x => x.CreateObjectSet<FakeEntity>()).Returns(mockObjectSet.Object);

        //act
        mockContext.Object.DeleteAllObjects<FakeEntity>();

        //assert
        mockContext.Verify(x => x.CreateObjectSet<FakeEntity>(), Times.Once());
        mockObjectSet.Verify(x => x.ToList(), Times.Once());
        mockObjectSet.Verify(x => x.DeleteObject(It.IsAny<FakeEntity>()), Times.Exactly(2));

    }
}
Run Code Online (Sandbox Code Playgroud)

现在,假设所有模拟类型(上下文和对象集)都具有您调用的方法virtual或类abstract.模拟接口通常限制性较小.

另外,如果你想对你的断言更加挑剔,以确保DeleteObject首先使用第一个实例调用,然后使用第二个实例,而不是第一个实例,那么你可以更改测试的那一部分.但这应该是一个很好的起点.

总结一下:

此特定测试应该只测试扩展方法中的代码.这意味着,它应该只确保您调用CreateObjectSet<>(),获取列表,然后调用DeleteObject每个列表.

它根本不应该关心是否确实DeleteObject()改变了ObjectSet(实际上它不会,因为它是一个模拟).这应该是该DeleteObject()方法测试的责任,但由于我假设这实际上是一个EF方法,所以不应该为第三方组件编写测试.