c# - 一次性方法的单元测试

标签 c# unit-testing

我在单元测试方面遇到了问题。 我有一个标准的 Reprository 和 UnitOfWork 模式。 例如,我有一个 UnitOfWork 类:

public class UnitOfWork : IDisposable
{
    private readonly MyDbContext _context;

    ... repositories 
    private IMyEntityRepository _myEntityRepository;
    ...
}

UnitOfWok 在程序的另一部分中使用,对实体进行一些特殊操作。例如,有一个使用 UnitOfWork 的方法:

public IEnumerable<MyClass> MyMethod()
  {
     using (_unitOfWork = new UnitOfWork())
     {
        var myEntities= _unitOfWork.MyEntityRepository.Get();

        var result = ... some logic to convert myEntities collection to IEnumerable<MyClass> 
        return result;
     }
  }

我的问题是,如果存在构造using(_unitOfWork = new UnitOfWork),如何为 MyMethod 编写单元测试?在那种情况下,我怎么能将假的 UnitOfWork 与假的上下文一起使用呢?感谢您的任何建议。

最佳答案

为了使您的类更易于伪造和测试,我建议尽可能抽象您的 UnitOfWorkRepositories,然后使用工厂将它们注入(inject)到依赖的类中在他们身上。

public interface IUnitOfWork : IDisposable {
    ... repositories 
    IMyEntityRepository MyEntityRepository;
    ...
}

你的 UnitOfWork 将从该接口(interface)派生

public class UnitOfWork : IUnitOfWork {...}

IUnitOfWorkFactory

public interface IUnitOfWorkFactory {
    IUnitOfWork Create();
}

有了它,依赖类就可以看起来像这样

public class MyDependentClass {
    private readonly IUnitOfWorkFactory unitOfWorkFactory;

    public MyDependentClass (IUnitOfWorkFactory unitOfWorkFactory) {
        this.unitOfWorkFactory = unitOfWorkFactory;
    }

    public IEnumerable<MyClass> MyMethod() {
         using (var _unitOfWork = unitOfWorkFactory.Create()) {
             var myEntities= _unitOfWork.MyEntityRepository.Get();

             var result = ... some logic to convert myEntities collection to IEnumerable<MyClass> 
             return result;
         }
    }
}

现在您可以模拟/伪造您的 UnitOfWorkRepositories 而无需伪造上下文。

假设您想测试/验证 UOW 在调用 MyMethod 之后是否实际被处理掉

(我使用 MoqFluentAssert 进行演示)

您可以按如下方式构建测试:

[TestMethod]
public void UOW_Should_Be_Disposed() {
    //Assert
    var fake_entities = Enumerable.Range(1, 10).Select(i => new MyEntity());
    var mockRepository = new Mock<IMyEntityRepository>();
    mockRepository.Setup(m => m.Get()).Returns(fake_entities);
    var mockUOW = new Mock<IUnitOfWork>();
    mockUOW.Setup(m => m.MyEntityRepository).Returns(mockRepository.Object);
    var mockFactory = new Mock<IUnitOfWorkFactory>();
    mockFactory.Setup(m => m.Create()).Returns(mockUOW.Object);

    //Act
    var sut = new MyDependentClass(mockFactory.Object);
    var output = sut.MyMethod().ToList();

    //Assert
    output.Should().NotBeNull();
    output.Should().HaveCount(10);
    output.Should().ContainItemsAssignableTo<MyClass>();
    mockUOW.Verify(m => m.Dispose());
}

上面显示了如何使用提到的框架轻松测试所有内容。

希望对你有帮助

关于c# - 一次性方法的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36635068/

相关文章:

c# - POS协议(protocol)串口通讯

python - 如何对使用 python-multiprocessing 的代码进行单元测试

Python 单元测试和测试发现

node.js - 用 proxyquire stub

c# - 将 ASP.NET WebAPI Minimal 中的 Program.cs 与 Startup.cs 分开以进行集成测试

c# - 如何防止应用程序被固定在 Windows 7 中?

c# - 使用 Azure 门户将 .nupkg 文件上传到我的 Azure 函数

java - 当我的第一个方法参数是String类型时,如何使用Powermock的Whitebox.invokeMethod(Object instance, Object...arguments)?

java - 用 JMockit 模拟私有(private)静态字段?

C# 方法和参数