こんにちは私はURLを入力として受け取り、それが到達可能かどうかを判断するメソッドを持っています。そのためのコードは次のとおりです。
_public static boolean isUrlAccessible(final String urlToValidate) throws WAGNetworkException {
URL url = null;
HttpURLConnection huc = null;
int responseCode = -1;
try {
url = new URL(urlToValidate);
huc = (HttpURLConnection) url.openConnection();
huc.setRequestMethod("HEAD");
huc.connect();
responseCode = huc.getResponseCode();
} catch (final UnknownHostException e) {
throw new WAGNetworkException(WAGConstants.INTERNET_CONNECTION_EXCEPTION);
} catch (IOException e) {
throw new WAGNetworkException(WAGConstants.INVALID_URL_EXCEPTION);
} finally {
if (huc != null) {
huc.disconnect();
}
}
return responseCode == 200;
}
_
PowerMockito
を使用してisUrlAccessible()メソッドの単体テストを行いたい。 whenNew()
を使用してURL
の作成をモックし、url.openConnection()
が呼び出されたときに、別のモックHttpURLConnection
オブジェクトを返す必要があると感じています。しかし、これを実装する方法がわかりませんか?私は正しい方向に進んでいますか?誰かがこれを実装するのを手伝ってくれますか?
解決策を見つけました。最初にURLクラスをモックし、次にHttpURLConnectionをモックし、url.openconnection()が呼び出されたら、このモックされたHttpURLConnectionオブジェクトを返し、最後にその応答コードを200に設定します。コードは次のとおりです。
@Test
public void function() throws Exception{
RuleEngineUtil r = new RuleEngineUtil();
URL u = PowerMockito.mock(URL.class);
String url = "http://www.sdsgle.com";
PowerMockito.whenNew(URL.class).withArguments(url).thenReturn(u);
HttpURLConnection huc = PowerMockito.mock(HttpURLConnection.class);
PowerMockito.when(u.openConnection()).thenReturn(huc);
PowerMockito.when(huc.getResponseCode()).thenReturn(200);
assertTrue(r.isUrlAccessible(url));
}
URLは最終クラスです。最終クラスをモックするために、JunitでPowerMockitoを使用できます。最終クラスをモックするには、テストクラスに@RunWith(PowerMockRunner.class)と@PrepareForTest({URL.class})のアノテーションを付ける必要があります。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ URL.class })
public class Test {
@Test
public void test() throws Exception {
URL url = PowerMockito.mock(URL.class);
HttpURLConnection huc = Mockito.mock(HttpURLConnection.class);
PowerMockito.when(url.openConnection()).thenReturn(huc);
assertTrue(url.openConnection() instanceof HttpURLConnection);
}
}
しかし、行PowerMockito.when(url.openConnection())。thenReturn(huc);では、次のエラーがスローされます。
Java.lang.AbstractMethodError
at Java.net.URL.openConnection(URL.Java:971)
at Java_net_URL$openConnection.call(Unknown Source)
このエラーを取り除くために、以下に示すようにTestクラスを変更できます。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ URL.class })
public class Test {
@Test
public void test() throws Exception {
public class UrlWrapper {
URL url;
public UrlWrapper(String spec) throws MalformedURLException {
url = new URL(spec);
}
public URLConnection openConnection() throws IOException {
return url.openConnection();
}
}
UrlWrapper url = Mockito.mock(UrlWrapper.class);
HttpURLConnection huc = Mockito.mock(HttpURLConnection.class);
PowerMockito.when(url.openConnection()).thenReturn(huc);
assertTrue(url.openConnection() instanceof HttpURLConnection);
}
}
訪問: https://programmingproblemsandsolutions.blogspot.com/2019/04/abstractmethoderror-is-thrown-on.html
新しいURLインスタンスをモックできます
whenNew(URL.class)..
そのwhenNew呼び出しから、以前に作成したモックオブジェクトを返すようにしてください。
URL mockUrl = Mockito.mock(URL.class);
whenNew(URL.class).....thenReturn(mockUrl );
次に、必要に応じてモックに動作を追加できます。
mockito
ライブラリを介してJava.net.URLクラスをモックするには、次の手順を実行する必要があります。
mock-maker-inline
ファイルへのテキスト。コード:
package myproject;
import org.junit.Test;
import Java.net.HttpURLConnection;
import Java.net.URL;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class Test {
@Test
public void test() throws Exception {
URL url = mock(URL.class);
HttpURLConnection huc = mock(HttpURLConnection.class);
when(url.openConnection()).thenReturn(huc);
assertTrue(url.openConnection() instanceof HttpURLConnection);
}
}
JMockitモックAPIを使用すると、はるかに簡単になります(さらに、モックを使用しない場合はさらに簡単になります)。
import Java.io.*;
import Java.net.*;
import org.junit.*;
import static org.junit.Assert.*;
import mockit.*;
public final class ExampleURLTest {
public static final class ClassUnderTest {
public static boolean isUrlAccessible(String urlToValidate) throws IOException {
HttpURLConnection huc = null;
int responseCode;
try {
URL url = new URL(urlToValidate);
huc = (HttpURLConnection) url.openConnection();
huc.setRequestMethod("HEAD");
huc.connect();
responseCode = huc.getResponseCode();
}
finally {
if (huc != null) {
huc.disconnect();
}
}
return responseCode == 200;
}
}
// Proper tests, no unnecessary mocking ///////////////////////////////////////
@Test
public void checkAccessibleUrl() throws Exception {
boolean accessible = ClassUnderTest.isUrlAccessible("http://google.com");
assertTrue(accessible);
}
@Test(expected = UnknownHostException.class)
public void checkInaccessibleUrl() throws Exception {
ClassUnderTest.isUrlAccessible("http://inaccessible12345.com");
}
@Test
public void checkUrlWhichReturnsUnexpectedResponseCode(
@Mocked URL anyURL, @Mocked HttpURLConnection mockConn
) throws Exception {
new Expectations() {{ mockConn.getResponseCode(); result = -1; }};
boolean accessible = ClassUnderTest.isUrlAccessible("http://invalidResource.com");
assertFalse(accessible);
}
// Lame tests with unnecessary mocking ////////////////////////////////////////
@Test
public void checkAccessibleUrl_withUnnecessaryMocking(
@Mocked URL anyURL, @Mocked HttpURLConnection mockConn
) throws Exception {
new Expectations() {{ mockConn.getResponseCode(); result = 200; }};
boolean accessible = ClassUnderTest.isUrlAccessible("http://google.com");
assertTrue(accessible);
}
@Test(expected = UnknownHostException.class)
public void checkInaccessibleUrl_withUnnecessaryMocking(
@Mocked URL anyURL, @Mocked HttpURLConnection mockConn
) throws Exception {
new Expectations() {{ mockConn.connect(); result = new UnknownHostException(); }};
ClassUnderTest.isUrlAccessible("http://inaccessible12345.com");
}
}
(JDK8および9のJMockit1.47で検証済み。)
このスレッドにはいくつかの良い提案がありますが、これらのサードパーティライブラリの使用に興味がない場合は、ここで簡単に解決できます。
public class MockHttpURLConnection extends HttpURLConnection {
private int responseCode;
private URL url;
private InputStream inputStream;
public MockHttpURLConnection(URL u){
super(null);
this.url=u;
}
@Override
public int getResponseCode() {
return responseCode;
}
public void setResponseCode(int responseCode) {
this.responseCode = responseCode;
}
@Override
public URL getURL() {
return url;
}
public void setUrl(URL url) {
this.url = url;
}
@Override
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public void disconnect() {
}
@Override
public boolean usingProxy() {
return false;
}
@Override
public void connect() throws IOException {
}
}
そして、これはあなたが望ましい行動を設定する方法です
MockHttpURLConnection httpURLConnection=new MockHttpURLConnection(new URL("my_fancy_url"));
InputStream stream=new ByteArrayInputStream(json_response.getBytes());
httpURLConnection.setInputStream(stream);
httpURLConnection.setResponseCode(200);
注:HttpUrlConnection
から3つのメソッドをモックするだけです。さらに多くのメソッドを使用している場合は、それらもモックであることを確認する必要があります。