[UnitTest04]-Moq判断方法的执行情况

本文介绍如何使用Moq框架进行单元测试,通过示例展示了如何验证特定条件下的方法调用与返回值,确保代码逻辑正确且未调用不应被触发的方法。

       通常我们会根据参数决定调用哪个函数,这时候我们写单元测试要做两件事情,一件事情是确保被调用的函数输出了正确的结果,另一件事情是确保不应该被调用的方法是没有被调用的。即,该做事的函数做了正确的事情,不该做事情的函数没有被调用。下面的例子例子演示如何使用It.IsAny<T>()及Verfiy()。

       IMoqTest接口

       public interface IMoqTest
       {
        double CalcArea(AreaType type, double r);

        double CalcRectangle(double r);

        double CalcCircle(double r);
       }

       MoqTeste类

       public enum AreaType
    {
        Circle,
        Rectangle,
        None
    }

public double CalcArea(AreaType type,double r)
        {
            double result = 0;
            switch (type)
            { 
                case AreaType.Circle:
                    result = CalcCircle(r);
                    break;
                case AreaType.Rectangle:
                    result = CalcRectangle(r); 
                    break;
            }
            return result;
        }

        public double CalcRectangle(double r)
        {
            return r * r;
        }

        public double CalcCircle(double r)
        {
            return Math.PI * Math.Pow(r, 2);
        }

        TestMethod

        [TestMethod]
        public void TestCalcArea_IfAreaTypeIsNone_ThenReturnZero()
        {
            AreaType type = AreaType.None;
            var moqTest = new Mock<IMoqTest>();
            moqTest.Setup(x => x.CalcArea(type, 3)).Returns(0);

            moqTest.Verify(x => x.CalcCircle(It.IsAny<double>()),Times.Never());
            moqTest.Verify(x => x.CalcRectangle(It.IsAny<double>()), Times.Never());

            Assert.AreEqual(0, moqTest.Object.CalcArea(type, 3));
        }

        同样是先Mock一个对象,然后调用setup,在Assert之前verfy两个方法都有没有被调用。

<think>根据用户需求,用户希望使用unittest框架测试登录、修改密码和登出功能的示例代码。我们将设计三个测试用例:test_login,test_change_password,test_logout。假设我们有一个简单的用户认证系统,我们将模拟这些功能。注意:在实际应用中,我们需要根据具体的应用逻辑(如Web框架、数据库操作等)来编写测试代码。这里我们将使用一个模拟的User类来代表用户系统,以便于编写测试。步骤:1.导入unittest模块。2.创建一个测试类,例如TestUserFunctions,继承unittest.TestCase。3.在测试类中,可以设置setUp和tearDown方法(如果需要)。4.编写测试方法:test_login,test_change_password,test_logout。5.在每个测试方法中,编写具体的测试步骤和断言。注意:由于登录、修改密码和登出通常是连续的操作,但测试用例之间应该是独立的。因此,每个测试用例都应该能够独立运行,不依赖于其他测试用例的状态。我们可以通过在每个测试用例开始前创建新的用户对象或重置状态来实现。下面是一个示例代码,我们模拟一个简单的用户认证系统:-用户登录:输入用户名和密码,返回登录是否成功。-修改密码:需要先登录,然后修改密码,再验证新密码。-登出:退出登录状态。注意:在实际测试中,我们可能需要模拟网络请求或使用测试数据库。这里为了简单,我们用一个内存中的用户字典来模拟。示例代码结构如下:</think>以下是使用unittest测试登录、修改密码和登出功能的示例代码,结合了引用[1][2][4][5]中的测试实践: ```python import unittest import logging from ddddocr import DdddOcr # 验证码识别库(引用[5]) from user_system import UserSystem # 假设的用户系统模块 # 配置测试日志(引用[2]) logging.basicConfig( filename='auth_test.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) class TestAuthFunctions(unittest.TestCase): """测试用户认证功能:登录/修改密码/登出""" @classmethod def setUpClass(cls): """创建测试用户""" cls.user = UserSystem() cls.user.create_user("test_user", "OldPass123!", "user@test.com") logging.info("测试用户创建完成") def setUp(self): """每个测试前的初始化""" self.user.reset_session() logging.info(f"开始执行测试: {self._testMethodName}") # 测试登录功能(引用[1]) def test_login_success(self): """测试成功登录场景""" result = self.user.login("test_user", "OldPass123!") self.assertTrue(result, "登录失败") self.assertEqual(self.user.get_current_user(), "test_user") logging.info("登录成功测试通过") # 验证码处理(引用[5]) def test_login_with_captcha(self): """测试带验证码的登录""" captcha_img = self.user.get_captcha_image() captcha = DdddOcr().classification(captcha_img) result = self.user.login("test_user", "OldPass123!", captcha) self.assertTrue(result, "验证码登录失败") # 测试修改密码功能 def test_password_change(self): """测试密码修改流程""" # 先登录 self.user.login("test_user", "OldPass123!") # 修改密码 result = self.user.change_password("OldPass123!", "NewPass456@") self.assertTrue(result, "密码修改失败") # 用新密码登录验证 self.user.logout() login_result = self.user.login("test_user", "NewPass456@") self.assertTrue(login_result, "新密码登录失败") logging.info("密码修改测试通过") # 测试登出功能(引用[4]) def test_logout(self): """测试登出功能""" self.user.login("test_user", "OldPass123!") self.user.logout() self.assertIsNone(self.user.get_current_user(), "登出失败") logging.info("登出功能测试通过") @classmethod def tearDownClass(cls): """清理测试数据""" cls.user.delete_user("test_user") logging.info("测试用户已清理") if __name__ == "__main__": # 使用标记运行特定测试(引用[1]) unittest.main(argv=['', '-m', 'login or change_password or logout']) ``` ### 关键实现说明: 1. **测试结构**: - `setUpClass`:创建测试用户(引用[4]的测试数据准备) - `setUp`/`tearDown`:每个测试前后的初始化和清理 - 独立测试方法:登录/修改密码/登出 2. **核心功能测试**: - **登录验证**:凭证校验和会话状态检查 - **密码修改**:包含旧密码验证和新密码生效检查 - **登出功能**:会话终止验证 3. **增强实践**: - 验证码处理:使用ddddocr库识别(引用[5]) - 日志跟踪:关键操作记录日志(引用[2]) - 标记执行:通过`-m`参数选择测试范围(引用[1]) 4. **断言方法**: - `assertTrue`:验证操作返回结果 - `assertIsNone`:验证登出后用户状态 - `assertEqual`:验证登录用户身份 ### 测试执行方式: ```bash # 运行全部认证测试 python test_auth.py # 选择性运行(引用[1]) python test_auth.py -m login # 仅登录测试 python test_auth.py -m change_password # 仅密码修改测试 ``` 此方案实现了: 1. 测试用例间的隔离(每个测试独立会话) 2. 关键操作的日志追踪 3. 自动化验证码处理 4. 灵活的测试组合执行 5. 符合unittest的标准测试结构 [^1]: 从以上运行结果可以看出,只有被选择的标记用例被运行 组合运行用例 [^2]: 在测试执行过程中,日志记录是跟踪测试状态和调试问题的关键 [^4]: 做过多接口联调的测试吗?...通过接口调试来进行测试 [^5]: dddd_ocr:识别验证码
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值