如何在asp.net中创建将记录更新到数据库的单元测试

如何在asp.net中创建将记录更新到数据库的单元测试,asp.net,unit-testing,Asp.net,Unit Testing,如何创建将记录更新到asp.net数据库中的单元测试?虽然从技术上讲,我们不称之为“单元测试”,但称之为“集成测试”(正如Oded所解释的),您可以使用单元测试框架,如MSTest(Visual Studio 2008/2010 professional的一部分)或免费的单元测试框架,比如努尼特 然而,测试ASP.NET web项目通常相当困难,尤其是当您将所有逻辑都放在网页中时。最好的做法是将您的所有业务逻辑提取到一个单独的层(通常是解决方案中的一个单独的项目),并从web页面中调用该逻辑。但

如何创建将记录更新到asp.net数据库中的单元测试?虽然从技术上讲,我们不称之为“单元测试”,但称之为“集成测试”(正如Oded所解释的),您可以使用单元测试框架,如MSTest(Visual Studio 2008/2010 professional的一部分)或免费的单元测试框架,比如努尼特

然而,测试ASP.NET web项目通常相当困难,尤其是当您将所有逻辑都放在网页中时。最好的做法是将您的所有业务逻辑提取到一个单独的层(通常是解决方案中的一个单独的项目),并从web页面中调用该逻辑。但也许你已经有了这种分离,这将是伟大的

这样,您也可以在测试中调用此逻辑。对于集成测试,最好有一个单独的测试数据库。测试数据库必须包含一组已知(且稳定)的数据(或完全为空)。不要使用生产数据库的副本,因为当数据更改时,测试可能会突然失败。此外,您还应该确保数据库中由集成测试所做的所有更改都应该回滚。否则,测试数据库中的数据会不断变化,这可能会导致测试突然失败

我总是在集成测试中使用
TransactionScope
(在生产代码中从未使用)。这确保了所有数据都将回滚。下面是使用MSTest时此类集成测试的示例:

[TestClass]
public class CustomerMovedCommandTests
{
    // This test test whether the Execute method of the
    // CustomerMovedCommand class in the business layer
    // does the expected changes in the database.
    [TestMethod]
    public void Execute_WithValidAddress_Succeeds()
    {
        using (new TransactionScope())
        {
            // Arrange
            int custId = 100;

            using (var db = new ContextFactory.CreateContext())
            {
                // Insert customer 100 into test database.
                db.Customers.InsertOnSubmit(new Customer()
                {
                    Id = custId, City = "London", Country = "UK"
                });

                db.SubmitChanges();
            }                

            string expectedCity = "New York";
            string expectedCountry = "USA";

            var command = new CustomerMovedCommand();
            command.CustomerId = custId;
            command.NewAddress = new Address()
            {
                City = expectedCity, Country = expectedCountry
            };

            // Act
            command.Execute();

            // Assert
            using (var db = new ContextFactory.CreateContext())
            {
                var c = db.Customers.Single(c => c.Id == custId);

                Assert.AreEqual(expectedCity, c.City);
                Assert.AreEqual(expectedCountry, c.Country);
            }
        } // Dispose rolls back everything.
    }
}

我希望这会有所帮助,但下次,请在您的问题中更具体一点。

如果您要更新数据库中的记录,这是一个集成测试,而不是单元测试。“如果测试与数据库对话,则它不是单元测试。它通过网络进行通信。它涉及文件系统。[…]”——Michael“有效使用遗留代码”Feathers,2005[很好的解释。关于“单元测试”,我将添加您可以“模拟”您的层。原则是尽可能模拟真实情况下发生的情况,以验证您的代码,而不做真实的事情:影响您的数据、文件或进程……数据模拟将模拟在数据库中执行的操作,但不会连接或删除访问数据库。我想这不是您想要检查的,而是将数据访问测试(单元测试)与数据库映射测试(集成测试)隔离开来的一种方式。模拟通常是一种“单元测试”,因为环境无关紧要。@JoeBilly:我同意。集成测试应该是最后的手段,您应该尝试使架构单元测试友好。但是,这样做需要很多努力(和经验)。作为一名顾问,我经常建议经验不足的团队开始进行集成测试,因为我对他们的体系结构要求较少。而LINQ似乎让事情变得更糟:您永远无法确定您的O/RM是否支持您编写的LINQ查询。正因为如此,我喜欢看到在实体框架中添加一个内存中的提供程序,以行为与真正的EF数据库提供程序完全相同。