對於簡單的In-Container單元測試,您可以使用stub的方式,stub即將真實系統的一部份引入您的程式之中,讓您的程式可以與這一個部份進行交互,而不一定要將整個程式置於系統之中。
stub的好處是,有時您并不是要測試程式與整個系統的行為,并且您也不是每次都可以將程式丟到系統之上運行,試想,您不能為了測試您的單元,而要求真正在服務客戶的系統不斷的重啟。
對於In-Container測試采取stub的方式,自然就是實現Container的部份功能,并將測試置於其中,在這邊您可以使用 Jetty [http://jetty.mortbay.org/jetty/index.html],它是個Java撰寫的HTTP伺服器,本身也是個 Container,Cactus集成了Jetty,并提供與測試相關的簡便類別。
使用Cactus+Jetty執行測試,在更大的程度上隱藏了測試運行過程的細節,您不必關心Redirector Proxy,更不一定要關心TestCase在客戶端與伺服端的行為,運行起來就如同在運作一個JUnit測試。
使用Cactus+Jetty進行測試時,Jetty會在測試開始前完成啟動,接著進行相關測試,然後Jetty會自動關閉,這很方便,另一方面,啟動 Jetty會快的多了。
要使用Cactus+Jetty,請將Cactus下載後的lib目錄中的commons-logging-xxx.jar、 aspectjrt-xxx.jar、cactus-xxx.jar、commons-httpclient-xxx.jar、junit- xxx.jar以及org.mortbay.jetty-xxx.jar設定至CLASSPATH。
接著撰寫測試案例:
- LoginServletTest.java
1
package onlyfun.caterpillar.test;
2
3
import junit.framework.Test;
4
import junit.framework.TestSuite;
5
import org.apache.cactus.ServletTestCase;
6
import org.apache.cactus.WebRequest;
7
import org.apache.cactus.extension.jetty.JettyTestSetup;
8
import onlyfun.caterpillar.LoginServlet;
9
10
public class LoginServletTest extends ServletTestCase
11

{
12
public static Test suite()
13
{
14
System.setProperty("cactus.contextURL", "http://localhost:8080/cactusDemo");
15
TestSuite suite = new TestSuite();
16
suite.addTestSuite(LoginServletTest.class);
17
return new JettyTestSetup(suite);
18
}
19
20
public void beginValidUser(WebRequest webRequest)
21
{
22
webRequest.addParameter("username", "justin");
23
webRequest.addParameter("password", "123456");
24
}
25
26
public void testValidUser()
27
{
28
LoginServlet loginServlet = new LoginServlet();
29
assertTrue(loginServlet.isValidUser(request));
30
}
31
32
public void beginInValidUser(WebRequest webRequest)
33
{
34
webRequest.addParameter("username", "guest");
35
webRequest.addParameter("password", "123456");
36
}
37
38
public void testInValidUser()
39
{
40
LoginServlet loginServlet = new LoginServlet();
41
assertFalse(loginServlet.isValidUser(request));
42
}
43
44
public static void main(String[] args)
45
{
46
junit.textui.TestRunner.run(LoginServletTest.suite());
47
}
48
}
49

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

在這邊要特別注意的是suite()方法,傳回了一個JettyTestSetup實例,如您所想的,這個實例除了運行TestSuite之外,它還會啟動Jetty。接下來依測試案例來完成程式:
- LoginServlet.java
1
package onlyfun.caterpillar;
2
3
import javax.servlet.http.*;
4
5
public class LoginServlet extends HttpServlet
6

{
7
public boolean isValidUser(HttpServletRequest request)
8
{
9
String username = request.getParameter("username");
10
String password = request.getParameter("password");
11
if (username == null || password == null || !username.equals("justin")
12
|| !password.equals("123456"))
13
{
14
return false;
15
}
16
else
17
{
18
return true;
19
}
20
}
21
}
22
然後就可以運行測試了,以下是測試的結果:
2

3

4

5

6



7

8



9

10

11

12

13



14

15

16

17



18

19

20

21

22

1
09:26:10.625 EVENT Starting Jetty/4.2.17
2
09:26:10.843 EVENT Started ServletHttpContext[/cactusDemo]
3
09:26:39.203 EVENT Started SocketListener on 0.0.0.0:8080
4
09:26:39.203 EVENT Started org.mortbay.jetty.Server@758fc9
5
..09:26:40.296 EVENT Stopping Acceptor
6
ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=8080]
7
09:26:40.296 EVENT Stopped SocketListener on 0.0.0.0:8080
8
09:26:40.296 EVENT Stopped ServletHttpContext[/cactusDemo]
9
09:26:40.296 EVENT Stopped org.mortbay.jetty.Server@758fc9
10
11
Time: 31.453
12
13
OK (2 tests)

2

3

4

5

6

7

8

9

10

11

12

13

如您所看到的,整個測試過程相當的簡易,Cactus+Jetty隱藏了更多的細節,您測試的行為幾乎與只使用JUnit時是一致的。