moq框架的真正目的

本文关键字:moq 框架 | 更新日期: 2023-09-27 18:02:41

我被要求使用Moq框架编写单元测试。我对如何在c#中编写Moq测试相当陌生。

我要通过这个MSDN链接

这是我现在所做的,因为我们正在使用依赖注入库

    //Repository
public interface IRepo
{
    IQueryable<MyModel> GetById( long userId );
}
public class Repo : BaseManager, IRepo
{
    public Repo(myDbContext context)
    {
        dbContext = context; //dbContext is from BaseManager class
    } 
    public IQueryable<MyModel> GetById( long userId )
    {
        return dbContext.MyModel.Where(x => x.IsActive && x.UserId == userId );
    }
}
//Test class
public class Test 
{
    Mock<DbSet<MyModel>> mockSet;
    Mock<myDbContext> mockContext;
    Mock<IRepo> mockRepository;
    [TestInitialize]
    public void Setup()
    {
        var data = new List<MyModel>{
            //3 records
        }.AsQueryable();
        var mockSet = new Mock<DbSet<MyModel>>();
        mockSet.As<IQueryable<MyModel>>().Setup(m => m.Provider).Returns(data.Provider);
        mockSet.As<IQueryable<MyModel>>().Setup(m => m.Expression).Returns(data.Expression);
        mockSet.As<IQueryable<MyModel>>().Setup(m => m.ElementType).Returns(data.ElementType);
        mockSet.As<IQueryable<MyModel>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
        var mockContext = new Mock<myDbContext>();
        mockContext.Setup(c => c.MyModel).Returns(mockSet.Object);
        mockRepository = new Mock<IRepo>();
        mockRepository.Setup(m => m.GetById(It.IsAny<long>())).Returns(data); //Here the GetById method is set to return all 3 records set in data object. 
    }
    [TestMethod]
    public void Test_Mock_For_Nothing()
    {
        var controller = new MyController(mockRepository.Object);
        var result = controller.GetById(1); //this will call GetById method in the repository
        Assert.AreEqual(result.Count(), 1);//This will fail as we will get count as 3
    }
}

因此,尽管我模拟了上下文和存储库,但存储库中的逻辑永远不会执行。因为GetById方法会根据虚拟数据直接返回3条记录的结果。

我希望根据存储库方法中的逻辑过滤掉虚拟数据。这在Moq中是否可行?

当存储库代码不被执行时,使用Moq框架的真正目的是什么?

moq框架的真正目的

既然已经模拟了存储库,但没有看到Controller逻辑,我不确定为什么需要模拟dbContext。但是,通过此测试,您实际上是在测试控制器逻辑,而不是测试存储库,因为您已经模拟了存储库以及存储库中的GetById返回的内容。

如果您希望测试存储库中的过滤器逻辑,则需要模拟dbContext(正如您所做的那样),并在测试中创建一个新的具体的存储库实例,并测试从调用GetById返回的数据。

模拟dbContext。MyModel,返回三个项目,并让Where调用执行过滤。

关于使用mock框架有很多有用的信息,但是每个人对于应该测试什么以及应该在单个单元测试中测试的单元大小都有稍微不同的意见,经验和个人偏好是这里的关键。

就您的测试而言,我想说使用mock框架甚至进行此测试几乎没有什么好处。我的想法:

1)如果你有一个存储库,写一个集成测试,因为你想证明你正在从数据库/web服务等返回数据

2)在您想要测试某些业务逻辑/行为的情况下使用Moq或RhinoMocks

使用单元测试来测试/强化业务逻辑。存储库中不应该有任何BL(业务逻辑)。使用MOCK框架时,您可以禁用不想测试的想法。-> Repository =对数据的访问。有了这个,你就可以改变你的方式,你得到你的数据(存储库),而不改变你的商业逻辑/UnitTests:)

PS:如果你想测试你的存储库或更多,你应该瞄准集成测试,甚至端到端测试。