如何单元测试将项添加到数据库的方法?

时间:2015-05-21 11:10:36

标签: c# database unit-testing

我有一个项目,我使用此方法将其添加到数据库中:

String json = "{\"0\":{    \"title\" :\"title 1\" ,   \"time\" : \"15:00\"    } ,\"1\":{    \"title\" : \"title 2\"  ,  \"time\" :\"16:00\"   }}";

Gson gson = new Gson();

Type type = new TypeToken<Map<Integer, News>>() {}.getType();

Map<Integer, News> map = gson.fromJson(json, type);

现在我必须为此方法编写单元测试,以检查项目是否正在添加到数据库中。我不知道我应该怎么做,有人可以帮助我吗?

4 个答案:

答案 0 :(得分:5)

您的代码与ItemRepository和UnitOfWork实现相结合。理想情况下,您应该将它们分离并使用模拟来验证是否调用了正确的方法。

可能的解决方案:

  1. 使存储库成为您工作单元的属性
  2. 不要直接创建工作单元,使用工厂
  3. 使工厂成为您班级的依赖
  4. 在您的测试中,将工厂的模拟传递给您正在测试的类,返回模拟工作单元
  5. 在您的UoW模拟中返回存储库的模拟
  6. 验证是否在Repository mock和Unit of Work模拟中调用了正确的方法
  7. 这就是一个例子。我使用Moq作为模拟框架。并将测试方法放在课堂中,但你可以得到这个想法:

    class MyClass
    {
        private readonly IUnitOfWorkFactory _factory;
    
        public MyClass(IUnitOfWorkFactory factory)
        {
            _factory = factory;
        }
    
        public Messages addItem(Item item)
        {
            Messages resultMessage = Messages.Success;
    
            using (IUnitOfWork unitOfWork = _factory.GetUnitOfWork())
            {
                try
                {
                    unitOfWork.ItemRep.Insert(item);
    
                    unitOfWork.Commit();
                }
    
                catch (Exception e)
                {
                    Console.WriteLine(e.StackTrace);
                    resultMessage = Messages.DB_Failure;
                }
    
    
            }
    
            return resultMessage;
        }
    
    
        public void Test()
        {
            // Arrange
            var factoryMock = new Mock<IUnitOfWorkFactory>();
            var uowMock = new Mock<IUnitOfWork>();
            var repositoryMock = new Mock<IItemRepository>();
    
            factoryMock.Setup(f => f.GetUnitOfWork()).Returns(uowMock.Object);
            uowMock.Setup(u => u.ItemRep).Returns(repositoryMock.Object);
    
            var sut = new MyClass(factoryMock.Object);
    
            // Act
            var item = new Item();
            sut.addItem(item);
    
    
            // Assert
            repositoryMock.Verify(r => r.Insert(item), Times.Once);
            uowMock.Verify(u => u.Commit(), Times.Once);
        }
    }
    

答案 1 :(得分:1)

你说的目标是&#34;检查这个项目是否已添加到数据库&#34;。

这是你通常不会编写单元测试的东西,因为它是数据库的责任,大概你不是那个正在开发的人。

单元测试的一个更好的例子是模拟数据库并检查决定向数据库添加内容的逻辑。例如:

  1. 工作单位由客户/运营商描述。
  2. 您的组件在数据库中查询是否存在该项目。
  3. 不存在相应的项目。
  4. 您的组件将该项目添加到数据库中。
  5. 这是通过仅使用数据库的模拟来实现的,它正在测试您的代码,而不是数据库。

答案 2 :(得分:0)

正如您的方法目前所做的那样,它不能进行单元测试,因为它是硬编码写入数据库的。

传统方法是将IItemRepository的实例传递给方法,而不是让方法创建它。这样做然后你可以自由地创建一个模拟的IItemRepository实现,它可以报告写入数据库的内容。

答案 3 :(得分:0)

正如其他答案所建议的那样:尝试将测试中的类与困难/慢速分开,以测试数据库之类的依赖关系。您可以使用多种方法来实现此结果,但它们都归结为相同: 不要创建(新的)依赖项,这些依赖项会使您想要自己测试的代码(如unitofwork / repository)中的单元测试变得困难。相反,请询问来自外部世界的这些依赖关系(google Dependency Inversion / DI获取更多信息)。

如果您想使用真实数据库测试存储库的实现,我建议您通过存储库的公共API进行测试。不要自己编写“SELECT * FROM Items”查询,但如果可用,请使用repository.GetItem(...)方法。这样,您的测试就不那么脆弱,并且与存储库类的实际实现分离。