一、单元测试框架junit

1、目前存在的问题
① 目前的方法如果需要测试,都需要在main方法上调用。
② 目前的结果都需要我们人工对比。

2、使用步骤
右击junit-4.4.jar > Build Path > Add to Build Path

3、注意的细节
① 如果使用junit测试一个方法的时候,在junit窗口上显示绿条那么代表测试正确,如果是出现了红条,则代表该方法测试出现了异常不通过
② 如果点击方法名、 类名、包名、 工程名运行junit分别测试的是对应的方法,类、 包中的所有类的@Test方法,工程中的所有@Test方法
③ @Test测试的方法不能是static修饰与不能带有形参
④ 如果测试一个方法的时候需要准备测试的环境或者是清理测试的环境,那么可以@Before、 @After 、@BeforeClass、 @AfterClass这四个注解
区别:@Before、 @After 是在每个测试方法测试的时候都会调用一次, @BeforeClass、 @AfterClass是在所有的测试方法测试之前与测试之后调用一次而已

4、使用规范
① 一个类如果需要测试,那么该类就应该对应着一个测试类,测试类的命名规范 :被测试类的类名+ Test
② 一个被测试的方法一般对应着一个测试的方法,测试的方法的命名规范是:test+ 被测试的方法的方法名

public class Demo1.1{
	@Test //注解
	public void getMax(){
	    int a = 1;
	    int b = 5;
		int max = a>b?a:b;
		System.out.println("最大值:"+max);
	}
}
public class ToolTest {
	@Test
	public void testGetMax(){
		int max = Tool.getMax();
		/**
		if(max!=5){
			throw new RuntimeException();
		}else{
			System.out.println("最大值:"+ max);
		}
		**/
		
		//断言
		Assert.assertSame(5, max); // 期望值,真实值
        // Assert.assertSame(new String("abc"), "abc"); //false
        // Assert.assertEquals(new String("abc"), "abc"); //true
        // Assert.assertNull("aa"); //false
        // Assert.assertTrue(true);	//true
	}
}
public class Demo1.2{
	//准备测试的环境
	//@Before
	@BeforeClass
	public static void beforeRead(){
		System.out.println("准备测试环境成功...");
	}
	
	//读取文件数据
	@Test
	public void readFile() throws IOException{
		FileInputStream fileInputStream = new FileInputStream("F:\\a.txt");
		int content  = fileInputStream.read();
		System.out.println("内容:"+content);
	}
	
	@Test
	public void sort(){
		System.out.println("读取文件数据排序..");
	}

	//清理测试环境的方法
    // @After 
	@AfterClass
	public static void afterRead(){
		System.out.println("清理测试环境..");
	}
}

二、内省

1、用反射来做

public class Demo1.3 {
	public static void main(String[] args) throws Exception {
		Person p = (Person) getInstance();
		System.out.println(p);
		
	}
	//根据配置文件的内容生产对象的对象并且要把对象的属性值封装到对象中
	public static Object getInstance() throws Exception{
		BufferedReader bufferedReader = new BufferedReader(new FileReader("obj.txt"));
		String className =  bufferedReader.readLine(); //读取配置文件获取到完整的类名
		Class clazz = Class.forName(className);
		//通过class对象获取到无参的构造方法
		Constructor constructor = clazz.getConstructor(null);
		//创建对象
		Object o  = constructor.newInstance(null);
		//读取属性值
		String line = null;
		while((line = bufferedReader.readLine())!=null){
			String[] datas = line.split("=");
			//通过属性名获取到对应的Field对象。
			Field field = 	clazz.getDeclaredField(datas[0]);
			if(field.getType()==int.class){
				field.set(o, Integer.parseInt(datas[1]));
			}else{
				field.set(o, datas[1]);
			}	
		}
		return o;	
	}
}

obj.txt里面内容:

cn.itcast.introspector.Person
id=110
name=狗娃

2、内省:一个变态的反射
内省主要解决的问题: 把对象的属性数据封装到对象中。

public class Demo1.4{
	@Test
	public void getAllProperty() throws IntrospectionException{
		//Introspector 内省类
		BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
		//通过BeanInfo获取所有的属性描述其
		PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); //获取一个类中的所有属性描述器
		for(PropertyDescriptor p : descriptors){
			System.out.println(p.getReadMethod()); //get方法
		}	
	}
	@Test
	public void testProperty() throws Exception{
		Person p = new Person();
		//属性描述器
		PropertyDescriptor descriptor = new PropertyDescriptor("id", Person.class);
		//获取属性对应的get或者是set方法设置或者获取属性了
		Method m = descriptor.getWriteMethod(); //获取属性的set方法
		//执行该方法设置属性值
		m.invoke(p,110);
		Method readMethod = descriptor.getReadMethod(); //是获取属性的get方法	
		System.out.println(readMethod.invoke(p, null));
	}
}

3、BeanUtils:主要把对象的属性数据封装到对象中。

BeanUtils好处:
① BeanUtils设置属性值的时候,如果属性是基本数据类型,BeanUtils会自动转换数据类型。
② BeanUtils设置属性值的时候底层也是依赖于get或者Set方法设置以及获取属性值的。
③ BeanUtils设置属性值,如果设置的属性是其他的引用类型数据,那么这时候必须要注册一个类型转换器。

BeanUtils使用前 > 导包:commons-logging.jar、commons-beanutils-1.8.0.jar

public class Demo1.5{
	public static void main(String[] args) throws Exception {
		//从文件中读取到的数据都是字符串的数据,或者是表单提交的数据获取到的时候也是字符串的数据。
		String id ="110";
		String name="张三";
		String salary = "1000.0";
		String birthday = "2018-8-6";
		
		//注册一个类型转换器
		//点击ConvertUtils关注源码:Attach Source… > External location > External File(关联文件源代码)
		ConvertUtils.register(new Converter() {
			@Override
			public Object convert(Class type, Object value) { // type:目前所遇到的数据类型 value:目前参数的值
				Date date = null;
				try{
					SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
					date = dateFormat.parse((String)value);
				}catch(Exception e){
					e.printStackTrace();
				}
				return date;
			}
		}, Date.class);

		Emp  e = new Emp();
		BeanUtils.setProperty(e, "id", id);
		BeanUtils.setProperty(e, "name",name);
		BeanUtils.setProperty(e, "salary",salary);
		BeanUtils.setProperty(e, "birthday",birthday);
		System.out.println(e);	
	}	
}

三、配置文件的路径问题

1、如果经常会发生变化的数据我们可以定义在配置文件上,比如数据库的用户名与密码。

2、配置文件的路径应该如何写呢?
① 绝对路径:一个文件的完整路径信息。一般绝对路径是包含有盘符的。
绝对路径的缺陷: 因为绝对路径是有盘符开头的,有些系统是没有盘符的。
② 相对路径:相对路径是相对于当前程序的路径。当前路径就是执行java命令的时候,控制台所在的路径。
③ 类文件路径:类文件路径就是使用了classpath的路径找对应的资源文件。
如果需要使用到类文件路径首先先要获取到一个Class对象。

public class DBUtil {
	static Properties properties ;
	static{
		try {
			properties = new Properties();
			//去加载配置文件
			Class clazz = DBUtil.class; 
			InputStream inputStream = clazz.getResourceAsStream("/db.properties"); //  "/"代表了Classpath的路径。getResourceAsStream 该方法里面使用的路径就是使用了类文件路径。
			properties.load(inputStream);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		System.out.println("当前路径:"+ new File(".").getAbsolutePath() );
		System.out.println("用户名:"+ properties.getProperty("userName")+" 密码:"+properties.getProperty("password"));	
	}
}

3、以后的数据库的用户名与密码一般都会保存到properties(配置文件)