Java的面向?qū)ο缶幊?/a>">Java的面向?qū)ο缶幊?/a>
724
2022-05-29
JUnit軟件測試技術(shù)(工具)
在項(xiàng)目中建立專門用戶測試的包結(jié)構(gòu)。
在Junit中,通過@Test注解,可以運(yùn)行一個方法。
★ Junit注解說明
使用了@Test注解應(yīng)該滿足以下條件:
1) 必須是無參數(shù)的非靜態(tài)方法。
2) 添加@Test注解的類,必須擁有一個無參數(shù)的公開構(gòu)造
★ JUnit測試示例演示
1、運(yùn)行完成后,可以在Junit的窗口上看到運(yùn)行所用的時間和結(jié)果信息。
2、被測試程序的運(yùn)行結(jié)果出現(xiàn)在控制臺(Console)上。
“項(xiàng)目”代碼:
package cn.hncu.user.dao.dao; /** * @author 陳浩翔 * @version 1.0 2016-5-4 */ public interface UserDao { public abstract void fun1()throws Exception; public abstract void fun2(); public abstract void fun3(); }
1
2
3
4
5
6
7
8
9
10
11
package cn.hncu.user.dao.impl; import cn.hncu.user.dao.dao.UserDao; /** * @author 陳浩翔 * @version 1.0 2016-5-4 */ public class UserDaoImpl implements UserDao{ @Override public void fun1() throws Exception { System.out.println("fun1...."); } @Override public void fun2() { System.out.println("fun2...."); } @Override public void fun3() { System.out.println("fun3...."); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package cn.hncu.user.dao.factory; import cn.hncu.user.dao.dao.UserDao; import cn.hncu.user.dao.impl.UserDaoImpl; /** * @author 陳浩翔 * @version 1.0 2016-5-4 */ public class UserDaoFactory { public static UserDao getUserDao(){ return new UserDaoImpl(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
隨便寫了幾個輸出。。。
下面的是測試代碼:
package cn.hncu.test; import org.junit.Test; import cn.hncu.user.dao.dao.UserDao; import cn.hncu.user.dao.factory.UserDaoFactory; import cn.hncu.user.dao.impl.UserDaoImpl; /** * @author 陳浩翔 * @version 1.0 2016-5-4 */ //使用@Test的條件2:該類必須具有一個無參構(gòu)造方法 public class TestUserDaoImpl { UserDao dao = UserDaoFactory.getUserDao(); /** * 測試fun1()方法 */ //使用@Test的條件1:測試方法必須是非靜態(tài)、無參 @Test public void testFun1(){ try { dao.fun1(); } catch (Exception e) { e.printStackTrace(); } } @Test public void testFun2() { dao.fun2(); } @Test public void testFun3() { dao.fun3(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
正確的演示結(jié)果:
錯誤的演示結(jié)果:(沒有無參構(gòu)造方法)
★ JUnit中的其它注解
@BeforeClass、@AfterClass、@Before、@After
package cn.hncu.test; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import cn.hncu.user.dao.dao.UserDao; import cn.hncu.user.dao.factory.UserDaoFactory; import cn.hncu.user.dao.impl.UserDaoImpl; /** * @author 陳浩翔 * @version 1.0 2016-5-4 */ public class TestUserDaoImpl2 { UserDao dao = UserDaoFactory.getUserDao(); //注意要加static @BeforeClass public static void initFirst(){ System.out.println("finishEnd..."); } //在每次運(yùn)行@Test方法之前,都會先運(yùn)行這個@Before的方法 @Before public void init(){ System.out.println("init..."); } @Test public void testFun1(){ try { dao.fun1(); } catch (Exception e) { e.printStackTrace(); } } /*運(yùn)行結(jié)果 finishEnd... init... fun1.... finish... finishEnd... */ @Test public void testFun2() { dao.fun2(); } /*運(yùn)行結(jié)果 finishEnd... init... fun2.... finish... finishEnd... */ @Test public void testFun3() { dao.fun3(); } /*運(yùn)行結(jié)果 finishEnd... init... fun3.... finish... finishEnd... */ //在每次運(yùn)行@Test方法之后,都會最后運(yùn)行這個@After的方法 @After public void finish(){ System.out.println("finish..."); } //注意要加static @AfterClass public static void finishEnd(){ System.out.println("finishEnd..."); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
注解 ( Annotation )
★ 元數(shù)據(jù)
所謂元數(shù)據(jù)就是數(shù)據(jù)的數(shù)據(jù)。也就是說,元數(shù)據(jù)是描述數(shù)據(jù)的。就象數(shù)據(jù)表中的字段一樣,每個字段描述了這個字段下的數(shù)據(jù)的含義。 元數(shù)據(jù)可以用于創(chuàng)建文檔,跟蹤代碼中的依賴性,甚至執(zhí)行基本編譯時檢查。許多元數(shù)據(jù)工具,如XDoclet,將這些功能添加到核心Java語言中,暫時成為Java編程功能的一部分。 一般來說,元數(shù)據(jù)的好處分為三類:文檔編制、編譯器檢查和代碼分析。代碼級文檔最常被引用。元數(shù)據(jù)提供了一種有用的方法來指明方法是否取決于其他方法,它們是否完整,特定類是否必須引用其他類,等等。
1
2
3
★ 什么是注解
Java中的注解就是Java源代碼的元數(shù)據(jù),也就是說注解是用來描述Java源代碼的。 基本語法就是:@后面跟注解的名稱。
像前面演示的那幾個都是注解。
★ Java中預(yù)定義注解
①Override:標(biāo)識某一個方法是否正確覆蓋了它的父類的方法。
(如果用了這個注解,但是父類中沒有這個方法,就會報錯)
②Deprecated:表示已經(jīng)不建議使用這個類成員了。 它是一個標(biāo)記注解。
(用了這個注解的,表示在下一個升級版本中,可能不會有這個方法了,但是會有類似功能的方法代替,會在注釋中提出)
③SuppressWarnings:用來抑制警告信息。
(例如:壓泛型的警告)
(這個是可以傳參進(jìn)去的,可以實(shí)現(xiàn)不同的功能)
自定義注解1
自定義注解的語法很簡單,跟定義接口類似,只是在名稱前面加上@符號。
★ 最簡單的自定義注解
public @interface MyAnno { }
1
2
★ 使用這個注解
和使用其他注解是一樣的
@MyAnno public class UserModel{ }
1
2
3
★ 為注解添加成員
//定義 public @interface MyAnno { public String schoolName(); }
1
2
3
4
//使用 @MyAnno(schoolName="湖南城市學(xué)院") public class UserModel{ }
1
2
3
4
5
★ 設(shè)置默認(rèn)值
//定義 public @interface MyAnno { public String schoolName() default "湖南城市學(xué)院"; }
1
2
3
4
//使用1 @MyAnno public class UserModel{ }
1
2
3
4
//使用2 @MyAnno(schoolName="城院Java高手訓(xùn)練營") public class UserModel{ }
1
2
3
4
對注解的注解
package cn.hncu.anno; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.TYPE}) public @interface MyAnno { }
1
2
3
4
5
6
7
8
9
10
11
12
13
☆指定目標(biāo) Target
在了解如何使用Target 之前,需要認(rèn)識另一個類,該類被稱為ElementType (通過API詳細(xì)學(xué)習(xí)) ,它實(shí)際上是一個枚舉。這個枚舉定義了注釋類型可應(yīng)用的不同程序元素。
//如果都不寫,就是隨便在哪里都可以用
@Target({ ElementType.TYPE, ElementType.METHOD})
1
//這個注解可以在哪里用,TYPE-可以在類上面用,METHOD-可以在方法上用
☆設(shè)置保持性 Retention
RetentionPolicy (通過API詳細(xì)學(xué)習(xí))枚舉類中定義了3種注解保持性,分別決定了Java 編譯器以何種方式處理注解。
@Retention(RetentionPolicy.RUNTIME)
1
//運(yùn)行時VM虛擬機(jī)也能識別這個注解,這個注解一直存在
@Retention(RetentionPolicy.SOURCE)
1
//class文件中有這個注解,但是VM虛擬機(jī)運(yùn)行時,忽略這個注解了。
(這是默認(rèn)的)
☆添加公共文檔 Documented
在默認(rèn)的情況下在使用javadoc自動生成文檔時,注解將被忽略掉。如果想在文檔中也包含注解,必須使用Documented為文檔注解。
☆設(shè)置繼承 Inherited
在默認(rèn)的情況下,父類的注解并不會被子類繼承。如果要繼承,就必須加上Inherited注解。
如何讀取注解
要讀取注解的內(nèi)容,就需要使用反射的技術(shù)。
注意:要想使用反射得到注釋信息,必須用@Retention(RetentionPolicy.RUNTIME)進(jìn)行注解。
/** * 分別讀取類上的@MyAnno注解 和 方法上的@MyAnno注解 */ @Test public void readAnno(){ //※※注意:MyAnno注解定義時,必須指定它的保持性為 RUNTIME,否則下面是讀取不出注解的 //以下方式是讀取“聲明在類上的”MyAnno注解 Class c = UserModel.class; //boolean boo = c.isAnnotationPresent(cn.hncu.anno.MyAnno.class); //boolean boo = c.isAnnotationPresent(MyAnno.class); boolean boo = (c.getAnnotation(MyAnno.class)!=null); System.out.println(boo); //以下方式是讀取“聲明在方法上的”MyAnno注解 Method ms[] = c.getDeclaredMethods(); for(Method m:ms){ if(m.isAnnotationPresent(MyAnno.class)){ System.out.println(m.getName()+"方法上有@MyAnno注解"); } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
結(jié)果:
true getAge方法上有@MyAnno注解 getId方法上有@MyAnno注解
1
2
3
4
類加載器
Java虛擬機(jī)中可以安裝多個類加載器,系統(tǒng)默認(rèn)三個主要類加載器,每個類負(fù)責(zé)加載特定位置的類:
BootStrap, ExtClassLoader, AppClassLoader
@Test public void systemLoaderDemo(){ ClassLoader loader = Person.class.getClassLoader(); System.out.println(loader);//AppClassLoader loader = loader.getParent(); System.out.println(loader);//ExtClassLoader loader = loader.getParent(); System.out.println(loader);//null }
1
2
3
4
5
6
7
8
9
因?yàn)锽ootStrap是最底層,用C寫的,我們不能訪問到,我們沒有權(quán)限,所以輸出就是null了。
類加載器也是Java類,因?yàn)槠渌莏ava類的類加載器本身也要被類加載器加載,顯然必須有第一個類加載器不是java類,這正是BootStrap。
Java虛擬機(jī)中的所有類裝載器采用具有父子關(guān)系的樹形結(jié)構(gòu)進(jìn)行組織,在實(shí)例化每個類裝載器對象時,需要為其指定一個父級類裝載器對象或者默認(rèn)采用系統(tǒng)類裝載器為其父級類加載。
☆類加載器的委托機(jī)制
通過API認(rèn)識ClassLoader類
當(dāng)Java虛擬機(jī)要加載一個類時,到底派出哪個類加載器去加載呢?
首先當(dāng)前線程的類加載器去加載線程中的第一個類。如果類A中引用了類B,Java虛擬機(jī)將使用加載類A的類裝載器來加載類B。
還可以直接調(diào)用ClassLoader.loadClass()方法來指定某個類加載器去加載某個類。
每個類加載器加載類時,又先委托給其上級類加載器。當(dāng)所有祖宗類加載器沒有加載到類,回到發(fā)起者類加載器,還加載不了,則拋ClassNotFoundException,不是再去找發(fā)起者類加載器的兒子,因?yàn)闆]有g(shù)etChild方法,即使有,那有多個兒子,找哪一個呢?
對著類加載器的層次結(jié)構(gòu)圖和委托加載原理,解釋先前將ClassLoaderTest輸出成jre/lib/ext目錄下的aa.jar包中后,運(yùn)行結(jié)果為ExtClassLoader的原因。
演示不是classpath下的類,系統(tǒng)類加載器是無法加載的
Person類:
package cn.hncu; /** * * @author 陳浩翔 * * @version 1.0 2016-5-4 */ public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Test public void loaderLocalClassDemo() throws ReflectiveOperationException{ Class c = Class.forName("cn.hncu.Person"); System.out.println(c); Object obj = c.newInstance(); System.out.println(obj); }
1
2
3
4
5
6
7
8
運(yùn)行結(jié)果:
class cn.hncu.Person Person [name=null, age=0]
1
2
3
再看:
我把Person.class移到d:\cn\hncu
//不是classpath下的類,系統(tǒng)類加載器是無法加載的---如果要加載,得自己寫類加載器 @Test public void loaderRemoteClassDemo() throws ReflectiveOperationException{ Class c = Class.forName("d:\cn\hncu\Person.class"); System.out.println(c); Object obj = c.newInstance(); System.out.println(obj); }
1
2
3
4
5
6
7
8
9
結(jié)果:
掛了,不能運(yùn)行了。
因?yàn)闆]有配置classpath。
對著類加載器的層次結(jié)構(gòu)圖和委托加載原理,解釋先前將ClassLoaderTest輸出成jre/lib/ext目錄下的aa.jar包中后,運(yùn)行結(jié)果為ExtClassLoader
必須是壓.class文件,不要壓縮.java文件。!!!!
package cn.hncu; /** * * @author 陳浩翔 * * @version 1.0 2016-5-4 */ public class LoaderDemo { public static void main(String[] args) { LoaderDemo a = new LoaderDemo(); System.out.println(a); } @Override public String toString() { return "隨便演示。。。chx"; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
先按照這個命令打包這個.java
package cn.hncu; /** * * @author 陳浩翔 * * @version 1.0 2016-5-4 */ public class LoaderDemo { public static void main(String[] args) { LoaderDemo a = new LoaderDemo(); System.out.println(a); } @Override public String toString() { return "湖南城院。。。隨便演示...chx"; } //改了沒用。已經(jīng)不會運(yùn)行這里的代碼了。 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
大家看輸出結(jié)果:
對著類加載器的層次結(jié)構(gòu)圖和委托加載原理,解釋先前將ClassLoaderTest輸出成jre/lib/ext目錄下的aa.jar包中后,運(yùn)行結(jié)果還是為ExtClassLoader。
也就是那三層從上到下,如果上面已經(jīng)有那個類了,就不會運(yùn)行下面的那個類:
BootStrap—>ExtClassLoader—>AppClassLoader(System classLoader)
大家再看看這個圖,是不是感覺容易理解一些了:
Java
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。