Asp.net Nunit和web应用程序

Asp.net Nunit和web应用程序,asp.net,unit-testing,testing,nunit,database-connection,Asp.net,Unit Testing,Testing,Nunit,Database Connection,我开始用“(NUnit)”学习单元测试。我知道这种类型的测试用于测试“类”、“函数”和“这些函数之间的交互” 在我的例子中,我开发“asp.net web应用程序” 我如何使用此测试来测试我的 页面(因为它被视为一个类) 以及在中使用的方法)和在哪个顺序?中,我有三层: 接口层(每页的.cs) 数据访问层(每个实体的类别)(DAL) 数据库层(包含到数据库的连接、打开连接、关闭连接等) 业务层(有时进行计算或某些单独的逻辑) 如何测试连接到数据库的方法 如何确保我的测试不浪费时间 有单元测试

我开始用“(NUnit)”学习单元测试。我知道这种类型的测试用于测试“类”、“函数”和“这些函数之间的交互”

在我的例子中,我开发“asp.net web应用程序”

  • 我如何使用此测试来测试我的 页面(因为它被视为一个类) 以及在中使用的方法)和在哪个顺序?中,我有三层:

  • 接口层(每页的.cs)

  • 数据访问层(每个实体的类别)(DAL)

  • 数据库层(包含到数据库的连接、打开连接、关闭连接等)

  • 业务层(有时进行计算或某些单独的逻辑)

  • 如何测试连接到数据库的方法

  • 如何确保我的测试不浪费时间

有单元测试和集成测试。单元测试是测试单个组件/类/方法/函数以及它们之间的交互,但只使用一个真实对象(测试中的系统SUT)和测试双重对象。双重测试可以分为存根和模拟。存根向SUT提供准备好的测试数据。这样可以将SUT与环境隔离。所以,您不必访问数据库、web或wcf服务等,每次都有相同的输入数据。模拟用于验证SUT是否按预期工作。SUT调用模拟对象上的方法,甚至不知道它不是真实对象。然后通过在模拟对象上断言来验证SUT是否有效。您可以手工编写存根和模拟,也可以使用多种模拟框架之一。其中之一就是

如果您想测试与数据库的交互,那就是集成测试,通常要困难得多。对于集成测试,您必须将外部资源设置为已知状态

让我们看看您的图层:

  • 您将无法对其进行单元测试。页面将与ASP.NET运行时紧密耦合。您应该尽量避免代码隐藏中有太多代码。只需从代码中调用一些对象并测试这些对象。您可以查看MVC设计模式。如果你必须测试你的页面,你应该看看。它自动化您的internet浏览器,单击页面上的按钮,并验证页面是否显示预期结果

  • 这是集成测试。您将数据放入数据库,然后将其读回并比较结果。测试后或测试前,您必须将测试数据库置于已知状态,以便测试可以重复。我的建议是在测试运行之前而不是测试运行之后设置数据库。这样,您就可以在测试失败后检查数据库中的内容

  • 我真的不知道这和第二点有什么不同

  • 这是单元测试。在测试中创建对象,调用其方法并验证结果

  • 如何测试连接到数据库的方法在第2点中进行了添加。 如何不浪费时间?这需要经验。我没有一般性的建议,所以不要测试没有任何逻辑的属性

    有关单元测试的详细信息,请参见此处:

    编辑:

    SUT,CUT-测试中的系统或类。这就是你要测试的。 测试双打-来自特技双打。他们在电影中扮演危险的场景,这样真正的演员就不必这样做了。彼此彼此。双重测试替换测试中的真实对象,以便您可以将SUT/切入测试与环境隔离

    让我们看看这门课

    
    public class NotTestableParty
    {
        public bool ShouldStartPreparing()
        {
            if (DateTime.Now.Date == new DateTime(2011, 12, 31))
            {
                Console.WriteLine("Prepare for party!");
                return true;
            }
            Console.WriteLine("Party is not today");
            return false;
        }
    }
    
    你将如何测试这个班在除夕夜做了它应该做的事情?你必须在除夕夜做:)

    现在看看修改后的Party类 存根示例:

        public class Party
        {
            private IClock clock;
    
            public Party(IClock clock)
            {
                this.clock = clock;
            }
    
            public bool ShouldStartPreparing()
            {
                if (clock.IsNewYearsEve())
                {
                    Console.WriteLine("Prepare for party!");
                    return true;
                }
                Console.WriteLine("Party is not today");
                return false;
            }
        }
    
        public interface IClock
        {
            bool IsNewYearsEve();
        }
    
        public class AlwaysNewYearsEveClock : IClock
        {
            public bool IsNewYearsEve()
            {
                return true;
            }
        }
    
    现在在测试中,你可以把假时钟传给聚会课

            var party = new Party(new AlwaysNewYearsEveClock());
            Assert.That(party.ShouldStartPreparing(), Is.True);
    
    现在你知道你的派对课是不是在除夕夜上课了。AlwaysNewearseveclock是一个存根

    现在看看这个类:

        public class UntestableCalculator
        {
            private Logger log = new Logger();
    
            public decimal Divide(decimal x, decimal y)
            {
                if (y == 0m)
                {
                    log.Log("Don't divide by 0");
                }
    
                return x / y;
            }
        }
    
        public class Logger
        {
            public void Log(string message)
            {
                // .. do some logging
            }
        }
    您将如何测试您的类记录消息。根据您的日志位置,您必须检查文件、数据库或其他位置。这不是单元测试,而是集成测试。为了进行单元测试,您需要这样做

        public class TestableCalculator
        {
            private ILogger log;
            public TestableCalculator(ILogger logger)
            {
                log = logger;
            }
            public decimal Divide(decimal x, decimal y)
            {
                if (y == 0m)
                {
                    log.Log("Don't divide by 0");
                }
                return x / y;
            }
        }
    
        public interface ILogger
        {
            void Log(string message);
        }
        public class FakeLogger : ILogger
        {
            public string LastLoggedMessage;
            public void Log(string message)
            {
                LastLoggedMessage = message;
            }
        }
    在测试中你可以

    var logger = new FakeLogger();
            var calculator = new TestableCalculator(logger);
            try
            {
                calculator.Divide(10, 0);
            }
            catch (DivideByZeroException ex)
            {
                Assert.That(logger.LastLoggedMessage, Is.EqualTo("Don't divide by 0"));
            }

    在这里,你断言伪造的日志。假记录器是模拟对象。

    非常感谢Peri,有些概念还不清楚,你能解释一下你所说的
    测试双精度(
    )、
    存根(
    )、
    模拟(
    )、
    SUT(
    )是什么意思吗。“我真的不知道这与第2点有什么不同。”数据库层直接使用数据库,数据访问层由每个实体(映射)的类组成,并使用数据库层访问数据和执行CRUD操作。