目录

黑马全套Java教程十

黑马全套Java教程(十)

文章目录

38 单元测试

单元测试 :针对最小的功能单元编写测试代码,Java程序最小的功能单元是 方法 ,因此,单元测试就是 针对Java方法的测试 ,进而检查方法的正确性

目前测试方法是怎么进行的,存在什么问题:

  • 只有一个main方法,如果一个方法的测试失败了,其他方法测试会受到影响
  • 无法得到测试的结果报告,需要程序员自己去观察测试是否成功
  • 无法实现自动化测试

Junit单元测试框架 :JUnit是使用Java语言实现的单元测试框架,它是开源的,Java开发者都应当学习并使用JUnit编写单元测试。此外,几乎所有的IDE工具都继承了JUnit,这样我们就可以直接在IDE中编写并运行JUnit,这样我们就可以直接在IDE中编写并运行JUnit测试,JUnit目前最新版本是。

JUnit优点

  1. JUnit可以灵活的选择执行哪些测试方法,可以一键执行全部测试方法。
  2. Junit可以生成全部方法的测试报告。
  3. 单元测试中的某个方法测试失败了,不会影响其他测试方法的测试。

https://i-blog.csdnimg.cn/blog_migrate/28e7804f8019caa9793204c9f355610a.png

UserService.java

//业务方法
public class UserService {
    public String loginName(String loginName, String passWord){
        if("admin".equals(loginName) && "123456".equals(passWord)){
            return "登录成功!";
        } else{
            return "用户名或密码出错!";
        }
    }

    public void selectNames(){
        System.out.println(10/0);
        System.out.println("查询全部用户名成功!");
    }
}

TestUserService.java

import org.junit.Assert;
import org.junit.Test;

//测试类
public class TestUserService {
    /*测试方法
        注意点
            1、必须是公开的,无参数,无返回值的方法
            2、测试方法必须使用@Test注解标记
     */
    @Test
    public void testLoginName(){
        UserService userService = new UserService();
        String rs = userService.loginName("admin", "123456");

        //进行预期结果的正确性测试:断言
        Assert.assertEquals("您的功能业务可能出现问题", "登录成功!", rs);
    }

    @Test
    public void testSelectNames(){
        UserService userService = new UserService();
        userService.selectNames();
    }
}

https://i-blog.csdnimg.cn/blog_migrate/3da3de876d94fa1a03554d15b5ecb58b.png

import jdk.jfr.BooleanFlag;
import org.junit.*;

//测试类
public class TestUserService {
    //修饰实例方法的
    @Before
    public void before(){
        System.out.println("===before方法执行一次===");
    }
    @After
    public void after(){
        System.out.println("===after方法执行一次===");
    }

    //修饰静态方法
    @BeforeClass
    public static void beforeClass(){
        System.out.println("===beforeClass方法执行一次===");
    }
    @AfterClass
    public static void afterClass(){
        System.out.println("===afterClass方法执行一次===");
    }

    /*测试方法
        注意点
            1、必须是公开的,无参数,无返回值的方法
            2、测试方法必须使用@Test注解标记
     */
    @Test
    public void testLoginName(){
        UserService userService = new UserService();
        String rs = userService.loginName("admin", "123456");

        //进行预期结果的正确性测试:断言
        Assert.assertEquals("您的功能业务可能出现问题", "登录成功!", rs);
    }

    @Test
    public void testSelectNames(){
        UserService userService = new UserService();
        userService.selectNames();
    }
}
===beforeClass方法执行一次===
===before方法执行一次===
===after方法执行一次===
===before方法执行一次===
5
查询全部用户名成功
===after方法执行一次===
===afterClass方法执行一次===

https://i-blog.csdnimg.cn/blog_migrate/99e3e9c595a38719176a9f1eb594085a.png

39 动态代理

https://i-blog.csdnimg.cn/blog_migrate/51eaeb45543b482d256e604b284e95b8.png

Star.java

package d9_proxy;

public class Star implements Skill{
    private String name;
    public Star(String name){
        this.name = name;
    }

    @Override
    public void jump(){
        System.out.println(name + "跳舞");
    }

    @Override
    public void sing(){
        System.out.println(name + "唱歌");
    }
}

Skill接口

package d9_proxy;

public interface Skill {
    void jump();
    void sing();
}

StarAgentProxy.java

package d9_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class StarAgentProxy {
    //设计一个方法来返回一个明星对象的代理对象
    public static Skill getProxy(Star obj){
        //为杨超越这个对象,生成一个代理对象
        return (Skill) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("收首付款。。。");
                        //真正的让杨超越去唱歌和跳舞。。。
                        //method  正在调用的方法对象    args代表这个方法的参数
                        Object rs = method.invoke(obj, args);
                        System.out.println("收尾款。。。");
                        return rs;
                    }
                });
    }
}

Test.java

package d9_proxy;

//目标:学习开发出一个动态代理的对象出来,理解动态代理的执行流程
public class Test {
    public static void main(String[] args) {
        //1. 创建一个对象(杨超越)  对象的类必须实现接口
        Star s = new Star("杨超越");
        // 为杨超越对象,生成一个代理对象(经纪人)
        Skill s2 = StarAgentProxy.getProxy(s);
        s2.jump();
        s2.sing();
    }
}

https://i-blog.csdnimg.cn/blog_migrate/f0d8698d3d96ee3ee4318dcfee3f820a.png

UserService.java

package d10_proxy2;

public interface UserService {
    String login(String loginName, String passWord);
    void deleteUser();
    String selectUsers();
}

UserServiceImpl.java

package d10_proxy2;

public class UserServiceImpl implements UserService{
    @Override
    public String login(String loginName, String passWord) {
        String rs = "登录名和密码错误";
        if("admin".equals(loginName) && "123456".equals(passWord)){
            rs = "登录成功";
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return rs;
    }

    @Override
    public void deleteUser() {
        try {
            System.out.println("您正在删除用户数据中。。。");
            Thread.sleep(2500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    @Override
    public String selectUsers() {
        String rs = "查询了10000个用户数据。。。";
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return rs;
    }
}

ProxyUtil.java

package d10_proxy2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyUtil {
    //通过一个静态方法,为用户业务对象返回一个代理对象
    public static UserService getProxy(UserService obj){
        return (UserService) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        long startTime = System.currentTimeMillis();

                        //真正触发对象的行为执行的
                        Object rs = method.invoke(obj, args);

                        long endTime = System.currentTimeMillis();
                        System.out.println(method.getName() + "方法耗时:" +  (endTime - startTime) / 1000.0 + "s");
                        return rs;
                    }
                });
    }
}

Test.java

package d10_proxy2;

//掌握使用动态代理解决问题,理解使用动态代理的优势
public class Test {
    public static void main(String[] args) {
        UserService userService = ProxyUtil.getProxy(new UserServiceImpl());
        System.out.println(userService.login("admin", "123456"));
        System.out.println(userService.selectUsers());
        userService.deleteUser();
    }
}

https://i-blog.csdnimg.cn/blog_migrate/319e39076af476578d4b13f324a2f9ae.png

40 XML

40.1 XML

XML是可扩展标记语言的缩写,它是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据

  • 纯文本,默认使用UTF-8编码;二是可嵌套

  • 如果把XML内容存为文件,那么它就是一个XML文件

  • XML的使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的消息

    https://i-blog.csdnimg.cn/blog_migrate/27a8d580be5f81a150be728a2e0f09de.png

    语法规则:

    https://i-blog.csdnimg.cn/blog_migrate/0f18d6a089a96a5e6dc3302545c270e7.png

    https://i-blog.csdnimg.cn/blog_migrate/0b103a906ddd6146a8e4f3da6aef7a3d.png

hello_world.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 我是注释: 跟标签只能有一个-->
<student>
    <name>女儿国网</name>
    <sex></sex>
    <hobby>唐僧</hobby>
    <info>
        <age>30</age>
        <addr>女儿国</addr>
    </info>
    <sql>
        select * from user where age &lt; 18;
        select * from user where age &lt; 18 &amp;&amp; age > 10;
        <![CDATA[
                select * from user where age < 18;
        ]]>
    </sql>
</student>

https://i-blog.csdnimg.cn/blog_migrate/57c228e62445b5e751c9819b282ade2e.png

文档约束 :是用来限定xml文件中的标签以及属性应该怎么写;以此强制约束程序员必须按照文档约束的规定来编写xml文件。

https://i-blog.csdnimg.cn/blog_migrate/a5bde4599e12fafe8c55a5505fb050f1.png

DTD约束文档

https://i-blog.csdnimg.cn/blog_migrate/d4766bde72c18d47b38d445fa57116e5.png

例:

https://i-blog.csdnimg.cn/blog_migrate/c4c36252057d9005fb966f58a0549aae.png

https://i-blog.csdnimg.cn/blog_migrate/6d35b08ced32f8e4e57431851f4baa92.png

DTD的问题:

  1. 可以约束XML文件的编写
  2. 不能约束具体的数据类型

schema约束

https://i-blog.csdnimg.cn/blog_migrate/4901fc7ec2e814a9c5fcc46f3007f4d0.png

https://i-blog.csdnimg.cn/blog_migrate/daeb3e6996dd075df36353182a12f568.png

例: https://i-blog.csdnimg.cn/blog_migrate/7820da864c4102d5362a8705f838816d.png

https://i-blog.csdnimg.cn/blog_migrate/e397278b6425d0aaeeb7cb0e2335e000.png

40.2 XML解析技术

什么是XML解析 :使用程序读取XML中的数据

两种解析方式:

  1. SAX解析
  2. DOM解析

https://i-blog.csdnimg.cn/blog_migrate/2a61915a1865b419be2a758c440b4989.png

https://i-blog.csdnimg.cn/blog_migrate/24dafedd80f4d51c331806106eebfbae.png

https://i-blog.csdnimg.cn/blog_migrate/2b676273e9402c627d4bba504cb37809.png

案例:dom4j解析

package d1_dom4j;

/*
 *  目标:学会使用dom4j解析XML文件中的数据
 *  1、导入dom4j框架
 *  2、准备一个XML文件
 */

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.io.File;
import java.io.InputStream;

public class Dom4JHelloWorldDemo1 {
    @Test
    public void parseXMLData() throws DocumentException {
        //1、创建一个Dom4j的解析对象,代表了整个dom4j框架
        SAXReader saxReader = new SAXReader();
        //2、把XML文件加载到内存中成为一个Document文档对象
        //Document document = saxReader.read(new File("xml-app\\src\\Contacts.xml"));   //需要通过模块名定位
        //直接在src下寻找文件,改了模块名没有影响
        InputStream is = Dom4JHelloWorldDemo1.class.getResourceAsStream("/Contacts.xml");
        Document document = saxReader.read(is);

        //3、获取根元素对象
        Element root = document.getRootElement();
        System.out.println(root.getName());
    }
}

https://i-blog.csdnimg.cn/blog_migrate/30e4b25cb25817e43552d23ed70f0855.png

package d1_dom4j;

/*
 *  目标:学会使用dom4j解析XML文件中的数据
 *  1、导入dom4j框架
 *  2、准备一个XML文件
 */

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import org.w3c.dom.Attr;

import java.io.File;
import java.io.InputStream;
import java.util.List;

public class Dom4JHelloWorldDemo1 {
    @Test
    public void parseXMLData() throws DocumentException {
        //1、创建一个Dom4j的解析对象,代表了整个dom4j框架
        SAXReader saxReader = new SAXReader();
        //2、把XML文件加载到内存中成为一个Document文档对象
        //Document document = saxReader.read(new File("xml-app\\src\\Contacts.xml"));   //需要通过模块名定位
        //直接在src下寻找文件,改了模块名没有影响
        InputStream is = Dom4JHelloWorldDemo1.class.getResourceAsStream("/Contacts.xml");
        Document document = saxReader.read(is);

        //3、获取根元素对象
        Element root = document.getRootElement();
        System.out.println(root.getName());

        //4、拿根元素下的全部子元素对象
        List<Element> sonEles = root.elements();
        for (Element sonEle : sonEles) {
            System.out.println(sonEle.getName());
        }

        //拿到某个子元素
        Element userEle = root.element("user");
        System.out.println(userEle.getName());
        //默认提取第一个子元素对象
        Element contact = root.element("contact");
        //获取子元素文本
        System.out.println(contact.elementText("name"));
        //去掉前后空格
        System.out.println(contact.elementTextTrim("name"));
        //根据元素获取属性值
        Attribute idAttr = contact.attribute("id");
        System.out.println(idAttr.getName() + "----->" + idAttr.getValue());
        //直接提取属性值
        System.out.println(contact.attributeValue("id"));
        System.out.println(contact.attributeValue("vip"));

        //获取当前元素下的子元素对象
        Element email = contact.element("email");
        System.out.println(email.getText());
    }
}

案例:

https://i-blog.csdnimg.cn/blog_migrate/c84a8e938a6aecdd58331c0fc434f437.png

package d1_dom4j;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

//需求:解析XML中的数据成为一个List集合对象
public class Dom4JTest2 {
    @Test
    public void parseToList() throws DocumentException {
        //需求:解析XML中的数据称为一个List集合对象
        //1、导入框架
        //2、创建SaxReader对象
        SAXReader saxReader = new SAXReader();
        //3、加载XML文件成为文档对象Document对象
        Document document = saxReader.read(Dom4JTest2.class.getResourceAsStream("/Contacts.xml"));
        //4、先拿根元素
        Element root = document.getRootElement();
        //5、提取contact子元素
        List<Element> contactEles = root.elements("contact");
        //6、准备一个ArrayList集合封装联系人信息
        List<Contact> contacts = new ArrayList<>();
        //7、遍历Contact子元素
        for (Element contactEle : contactEles) {
            //8、每个子元素都是一个联系人对象
            Contact contact = new Contact();
            contact.setId(Integer.valueOf(contactEle.attributeValue("id")));
            contact.setVip(Boolean.valueOf(contactEle.attributeValue("vip")));
            contact.setName(contactEle.attributeValue("Name"));
            contact.setGender(contactEle.attributeValue("gender").charAt(0));   //取一个字符
            contact.setEmail(contactEle.attributeValue("email"));
            //9、把联系人对象数据加入到List集合
            contacts.add(contact);
        }
        //10、遍历List集合
        for (Contact contact : contacts) {
            System.out.println(contact);
        }
    }
}

40.3 XPath

XPath使用路径表达式来定位XML文档中的元素节点或属性节点

https://i-blog.csdnimg.cn/blog_migrate/de8d647f43283d1c1876a594534a9644.png

总结

https://i-blog.csdnimg.cn/blog_migrate/aa3f3e185da18e816176b1a5e35d03f5.png

https://i-blog.csdnimg.cn/blog_migrate/d98c77f7824aa65576bbe33c8a29f454.png