![](/img/trans.png)
[英]How to write JUnit test of a class that uses anonymous inner class such as PreparedStatementSetter?
[英]How to write a jUnit test for a class that uses a network connection
我想知道使用jUnit測試在下面的類中測試方法“pushEvent()”的最佳方法是什么。 我的問題是,私有方法“callWebsite()”總是需要連接到網絡。 我怎樣才能避免這個要求或重構我的課程,我可以在沒有連接到網絡的情況下測試它?
class MyClass {
public String pushEvent (Event event) {
//do something here
String url = constructURL (event); //construct the website url
String response = callWebsite (url);
return response;
}
private String callWebsite (String url) {
try {
URL requestURL = new URL (url);
HttpURLConnection connection = null;
connection = (HttpURLConnection) requestURL.openConnection ();
String responseMessage = responseParser.getResponseMessage (connection);
return responseMessage;
} catch (MalformedURLException e) {
e.printStackTrace ();
return e.getMessage ();
} catch (IOException e) {
e.printStackTrace ();
return e.getMessage ();
}
}
}
您需要一個測試雙(存根)以允許隔離,簡單,單元測試。 以下是未經測試,但演示了這個想法。 使用依賴注入將允許您在測試時注入HttpURLConnection的測試版本。
public class MyClass()
{
private IHttpURLConnection httpUrlConnection;
public MyClass(IHttpURLConnection httpUrlConnection)
{
this.httpUrlConnection = httpUrlConnection;
}
public String pushEvent(Event event)
{
String url = constructURL(event);
String response = callWebsite(url);
return response;
}
}
然后,您創建一個存根(有時稱為模擬對象)作為具體實例的替代。
class TestHttpURLConnection : IHttpURLConnection { /* Methods */ }
您還將構建一個具體版本,供您的生產代碼使用。
class MyHttpURLConnection : IHttpURLConnection { /* Methods */ }
使用您的測試類( 適配器 ),您可以指定測試期間應該發生的事情。 模擬框架將使您能夠使用更少的代碼執行此操作,或者您可以手動連接它。 測試的最終結果是,您將設置對測試的期望,例如,在這種情況下,您可以將OpenConnection設置為返回一個真正的布爾值(順便說一下,這只是一個例子)。 然后,您的測試將斷言當此值為true時,PushEvent方法的返回值與某些預期結果匹配。 我暫時沒有正確地觸及Java,但是這里有一些建議的模擬框架 ,由StackOverflow成員指定。
可能的解決方案:您可以擴展此類,覆蓋callWebsite(您必須為此目的保護它) - 並且覆蓋方法編寫一些存根方法實現。
從略微不同的角度接近事物......
我不太擔心測試這個特定的課程。 其中的代碼非常簡單,雖然確保使用連接的功能測試會有所幫助,但單元級測試“可能”不是必需的。
相反,我專注於測試它所調用的實際上做某事的方法。 特別...
我從這一行測試了constructURL方法:
String url = constructURL (event);
確保它可以從不同的事件正確構造一個URL,並在它應該的時候拋出異常(可能是在一個無效的事件或null)。
我將從以下行測試該方法:
String responseMessage = responseParser.getResponseMessage (connection);
可能將任何“從連接中獲取信息”邏輯拉出到一個proc中,並且只留下“解析所述信息”的原始信息:
String responseMessage = responseParser.getResponseMessage(responseParser.getResponseFromConnection(connection));
或類似的規定。
想法是在一個方法中放置任何“必須處理外部數據源”代碼,並且在可以輕松測試的單獨方法中放置任何代碼邏輯。
作為Finglas關於模擬的有用答案的替代方案,考慮一種我們覆蓋callWebsite()功能的存根方法。 在我們對callWebsite的邏輯不像pushEvent()中調用的其他邏輯那樣感興趣的情況下,這非常有效。 要檢查的一件重要事情是使用正確的URL調用callWebsite。 所以,首先改變的是callWebsite()的方法簽名變為:
protected String callWebsite(String url){...}
現在我們創建一個這樣的存根類:
class MyClassStub extends MyClass {
private String callWebsiteUrl;
public static final String RESPONSE = "Response from callWebsite()";
protected String callWebsite(String url) {
//don't actually call the website, just hold onto the url it was going to use
callWebsiteUrl = url;
return RESPONSE;
}
public String getCallWebsiteUrl() {
return callWebsiteUrl;
}
}
最后在我們的JUnit測試中:
public class MyClassTest extends TestCase {
private MyClass classUnderTest;
protected void setUp() {
classUnderTest = new MyClassStub();
}
public void testPushEvent() { //could do with a more descriptive name
//create some Event object 'event' here
String response = classUnderTest.pushEvent(event);
//possibly have other assertions here
assertEquals("http://some.url",
(MyClassStub)classUnderTest.getCallWebsiteUrl());
//finally, check that the response from the callWebsite() hasn't been
//modified before being returned back from pushEvent()
assertEquals(MyClassStub.RESPONSE, response);
}
}
創建一個抽象類WebsiteCaller
,它將是ConcreteWebsiteCaller
和WebsiteCallerStub
的父級。
這個類應該有一個方法callWebsite (String url)
。 將您的callWebsite方法從MyClass
移動到ConcreteWebsiteCaller
。 而MyClass
看起來像:
class MyClass {
private WebsiteCaller caller;
public MyClass (WebsiteCaller caller) {
this.caller = caller;
}
public String pushEvent (Event event) {
//do something here
String url = constructURL (event); //construct the website url
String response = caller.callWebsite (url);
return response;
}
}
並以適合測試的某種方式在您的WebsiteCallerStub
中實現方法callWebsite
。
然后在你的單元測試中做這樣的事情:
@Test
public void testPushEvent() {
MyClass mc = new MyClass (new WebsiteCallerStub());
mc.pushEvent (new Event(...));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.