我们在我们想要模拟的一个Java类中有一个URL对象,但它是最后一个类,所以我们不能.我们不希望达到上述水平,并模拟InputStream,因为这仍然会给我们带来未经测试的代码(我们有严格的测试覆盖标准).
我已经尝试过jMockIt的反射功能,但是我们在Mac上工作,并且Java代理处理程序存在一些我无法解决的问题.
那么在junit测试中是否有任何不涉及使用真实URL的解决方案?
就像Rob说的,如果你想要的是模拟从URL返回的连接,你可以扩展URLStreamHandler
.例如,使用mockito:
final URLConnection mockUrlCon = mock(URLConnection.class); ByteArrayInputStream is = new ByteArrayInputStream( "".getBytes("UTF-8")); doReturn(is).when(mockUrlCon).getInputStream(); //make getLastModified() return first 10, then 11 when(mockUrlCon.getLastModified()).thenReturn((Long)10L, (Long)11L); URLStreamHandler stubUrlHandler = new URLStreamHandler() { @Override protected URLConnection openConnection(URL u) throws IOException { return mockUrlCon; } }; URL url = new URL("foo", "bar", 99, "/foobar", stubUrlHandler); doReturn(url).when(mockClassloader).getResource("pseudo-xml-path");
当我有不容易被嘲笑,因为它是最后的(或C#密封)一类,我平时的路线是编写类周围的包装和使用包装的地方我会用实际的类.然后我会根据需要模拟包装类.
我选择了以下内容:
public static URL getMockUrl(final String filename) throws IOException { final File file = new File("testdata/" + filename); assertTrue("Mock HTML File " + filename + " not found", file.exists()); final URLConnection mockConnection = Mockito.mock(URLConnection.class); given(mockConnection.getInputStream()).willReturn( new FileInputStream(file)); final URLStreamHandler handler = new URLStreamHandler() { @Override protected URLConnection openConnection(final URL arg0) throws IOException { return mockConnection; } }; final URL url = new URL("http://foo.bar", "foo.bar", 80, "", handler); return url; }
这给了我一个包含我的模拟数据的真实URL对象.
我使用了一个URLHandler,它允许我从类路径加载一个URL.所以以下
new URL("resource:///foo").openStream()
将从类路径中打开一个名为foo的文件.为此,我使用一个通用的实用程序库并注册一个处理程序.要使用此处理程序,您只需要调用:
com.healthmarketscience.common.util.resource.Handler.init();
并且资源URL现在可用.
如果您不想创建包装器:
注册一个URLStreamHandlerFactory
公开您想要的方法
模拟链
abstract public class AbstractPublicStreamHandler extends URLStreamHandler { @Override public URLConnection openConnection(URL url) throws IOException { return null; } } public class UrlTest { private URLStreamHandlerFactory urlStreamHandlerFactory; @Before public void setUp() throws Exception { urlStreamHandlerFactory = Mockito.mock(URLStreamHandlerFactory.class); URL.setURLStreamHandlerFactory(urlStreamHandlerFactory); } @Test public void should_return_mocked_url() throws Exception { // GIVEN AbstractPublicStreamHandler publicStreamHandler = Mockito.mock(AbstractPublicStreamHandler.class); Mockito.doReturn(publicStreamHandler).when(urlStreamHandlerFactory).createURLStreamHandler(Matchers.eq("http")); URLConnection mockedConnection = Mockito.mock(URLConnection.class); Mockito.doReturn(mockedConnection).when(publicStreamHandler).openConnection(Matchers.any(URL.class)); Mockito.doReturn(new ByteArrayInputStream("hello".getBytes("UTF-8"))).when(mockedConnection).getInputStream(); // WHEN URLConnection connection = new URL("http://localhost/").openConnection(); // THEN Assertions.assertThat(new MockUtil().isMock(connection)).isTrue(); Assertions.assertThat(IOUtils.toString(connection.getInputStream(), "UTF-8")).isEqualTo("hello"); } }
PS:我不知道如何在最后一行之后取消编号列表的自动间隔