黑马全套Java教程十
目录
黑马全套Java教程(十)
文章目录
38 单元测试
单元测试 :针对最小的功能单元编写测试代码,Java程序最小的功能单元是 方法 ,因此,单元测试就是 针对Java方法的测试 ,进而检查方法的正确性
目前测试方法是怎么进行的,存在什么问题:
- 只有一个main方法,如果一个方法的测试失败了,其他方法测试会受到影响
- 无法得到测试的结果报告,需要程序员自己去观察测试是否成功
- 无法实现自动化测试
Junit单元测试框架 :JUnit是使用Java语言实现的单元测试框架,它是开源的,Java开发者都应当学习并使用JUnit编写单元测试。此外,几乎所有的IDE工具都继承了JUnit,这样我们就可以直接在IDE中编写并运行JUnit,这样我们就可以直接在IDE中编写并运行JUnit测试,JUnit目前最新版本是。
JUnit优点 :
- JUnit可以灵活的选择执行哪些测试方法,可以一键执行全部测试方法。
- Junit可以生成全部方法的测试报告。
- 单元测试中的某个方法测试失败了,不会影响其他测试方法的测试。
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();
}
}
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方法执行一次===
39 动态代理
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();
}
}
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();
}
}
40 XML
40.1 XML
XML是可扩展标记语言的缩写,它是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据
纯文本,默认使用UTF-8编码;二是可嵌套
如果把XML内容存为文件,那么它就是一个XML文件
XML的使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的消息
语法规则:
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 < 18;
select * from user where age < 18 && age > 10;
<![CDATA[
select * from user where age < 18;
]]>
</sql>
</student>
文档约束 :是用来限定xml文件中的标签以及属性应该怎么写;以此强制约束程序员必须按照文档约束的规定来编写xml文件。
DTD约束文档
例:
DTD的问题:
- 可以约束XML文件的编写
- 不能约束具体的数据类型
schema约束
例:
40.2 XML解析技术
什么是XML解析 :使用程序读取XML中的数据
两种解析方式:
- SAX解析
- DOM解析
案例: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());
}
}
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());
}
}
案例:
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文档中的元素节点或属性节点