一.问题描述

在做自动化测试断言验证时,更新完用户信息后,拿着这个updateUserCase信息去数据库user表查询,如果返回不为空说明更新成功。
但是测试时发现断言执行失败

10:35:06.645 [main] DEBUG com.course.model.getUpdateUserInfo - ==>  Preparing: select * from user where id=? and username=? and sex=? and age=? 
10:35:06.646 [main] DEBUG com.course.model.getUpdateUserInfo - ==> Parameters: 12(Integer), 小兰1(String), 1(String), 1(String)
10:35:06.647 [main] DEBUG com.course.model.getUpdateUserInfo - <==      Total: 0
user is:null



java.lang.AssertionError: expected object to not be null

	at org.testng.Assert.fail(Assert.java:94)
	at org.testng.Assert.assertNotNull(Assert.java:423)
	at org.testng.Assert.assertNotNull(Assert.java:408)
	at com.course.cases.UpdateUserInfoTest.updateUserInfo(UpdateUserInfoTest.java:46)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:645)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
	at org.testng.TestRunner.privateRun(TestRunner.java:756)
	at org.testng.TestRunner.run(TestRunner.java:610)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:387)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:382)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
	at org.testng.SuiteRunner.run(SuiteRunner.java:289)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
	at org.testng.TestNG.runSuites(TestNG.java:1133)
	at org.testng.TestNG.run(TestNG.java:1104)
	at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
	at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:110)


二.问题解决

1.拿着这个SQL语句去sqlyog查询发现是能查询出结果的;
在这里插入图片描述

2.尝试在配置文件修改编码为utf-8

 <!-- 2.数据库连接地址 -->
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/java_auto_test?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai"/>
                <!-- 数据库用户... -->

再次运行仍然是失败的;

3.在网上看到

用字段拼接的方式,把#号改成
用#是走了预编译,你传过去的对于数据库来说都是参数值还不是字段,你这个需要拼接sql,所以用$,底层就是jdbc的statement

尝试将下面查询语句对应的#都改成$(会有SQL注入的风险,还是更建议用#)
在这里插入图片描述
再次运行发现还是失败。

4.想到检查pom文件,

<!--        5.mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>

  <!--        8.springboot依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

    </dependencies>

怀疑是不是我的mybatis-spring-boot-starter版本太低了,
尝试修改版本为2.1.0,

再次运行发现还是失败

5.偶然发现第一次运行测试代码断言会执行失败,第二次及以后就会成功了,也是很神奇,但是一直没找到原因

6.修改测试代码,传入userId,不传updateUserCase对象了;
在这里插入图片描述

在这里插入图片描述
再次运行发现断言执行成功了

11:10:40.206 [main] INFO com.course.cases.UpdateUserInfoTest - 请求http:localhost/v1/updateUserInfo的结果是------>1
11:10:40.206 [main] DEBUG com.course.model.getUpdateUserInfo - ==>  Preparing: select * from user where id=? 
11:10:40.206 [main] DEBUG com.course.model.getUpdateUserInfo - ==> Parameters: 12(Integer)
11:10:40.207 [main] DEBUG com.course.model.getUpdateUserInfo - <==      Total: 1
user is:User(id=12, userName=小兰3, password=111, age=13, sex=1, permission=1, isDelete=0)
db is:User(id=12, userName=小兰3, password=111, age=13, sex=1, permission=1, isDelete=0)
11:10:40.207 [main] INFO com.course.cases.UpdateUserInfoTest - ********updateUserInfo api 验证通过*********

但是结果不太对…显示的是修改之前的结果,这也就解释了为什么前面根据修改之后的结果去查询user得到的是空;

7.在服务端增加log发现服务端能查询出正确的更新后的结果


2021-06-11 11:22:55.417 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 调用SQL更新用户信息成功
2021-06-11 11:22:55.417 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 调用SQL更新的用户是:12
2021-06-11 11:22:55.418 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 更新后查到的user是:User(i
d=12, userName=小兰6, password=111, age=16, sex=1, permission=14, isDelete=0)


但是对测试代码debug发现还是旧值
在这里插入图片描述

8.检查代码发现我的sqlSession定义在TestConfig里且为静态的,而且被所有的测试方法公用;
SQLSession本身不是线程安全的,共用一个SQLsession的话,导致了事务问题

每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。

打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。
如下:
    SqlSession session = sqlSessionFactory.openSession();
    try {
          // do work
    } finally {
          session.close();
    }

修改为:在每次执行查询的时候新建一个SQLsession

        User resFromDatabase = MybatisUtils.openSession().selectOne(updateCase.getExpected(),userId);


9.再次运行,测试代码已能获得最新的记录信息
在这里插入图片描述


2021-06-11 11:33:35.345 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 调用SQL更新用户信息成功
2021-06-11 11:33:35.345 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 调用SQL更新的用户是:12
2021-06-11 11:33:35.346 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 更新后查到的user是:User(i
d=12, userName=小兰8, password=111, age=18, sex=1, permission=14, isDelete=0)


10.再把测试代码改回用updateCase查询,更新后的记录;

        User resFromDatabase = MybatisUtils.openSession().selectOne(updateCase.getExpected(),updateCase);


<!--    获取更新/删除后的用户信息-->
    <select id="getUpdateUserInfo" parameterType="com.course.model.UpdateUserInfoCase" resultMap="UserMap">
        select * from user
        <trim prefix="where" prefixOverrides="and">
            <if test="userId!=null and userId!=''">
                and id=#{userId}
            </if>
            <if test="userName!=null and userName!=''">
                and username=#{userName}
            </if>
            <if test="sex!=null and sex!=''">
                and sex=#{sex}
            </if>
            <if test="age!=null and age!=''">
                and age=#{age}
            </if>
            <if test="permission!=null and permission!=''">
                and permission=#{permission}
            </if>
            <if test="isDelete!=null and isDelete!=''">
                and is_delete=#{isDelete}
            </if>
        </trim>
    </select>

再次运行测试代码,终于成功了
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐