我有一个使用Record
的课程new URL(Record.SOURCE_URL)
。我有一个名为BaseTestController
的测试基类。每个其他测试类都扩展了这个。我想模仿new URL
,因为Record.SOURCE_URL
将无法在本地计算机上使用。
这就是我所拥有的:
@RunWith(PowerMockRunner.class)
@PrepareForTest(Record.class)
public abstract class BaseTestController {
@Before
public void setUp() {
PowerMockito.whenNew(URL.class).withArguments(Record.SOURCE_URL).thenReturn(PowerMockito.mock(URL.class));
}
}
这会返回错误:
java.lang.AbstractMethodError:java.net.URLStreamHandler.openConnection(Ljava / net / URL;)Ljava / net / URLConnection;
如何正确模拟我的网址类?
答案 0 :(得分:2)
恕我直言,使用 PowerMock 是对糟糕设计的投降。它通常表明您未能遵循单一责任模式和关注点分离。例如:如果URL对象对于所有测试都是相同的,那么它很可能应该作为构造函数参数传递给被测代码(CUT)......
PowerMock 也会更改(CUT)的字节代码,导致测试覆盖率工具无法正常工作。
同样拥有测试类的继承树是个坏主意。这是因为UnitTests是CUT的文档,测试基类中的代码隐藏了一些关于CUT依赖关系的重要信息。
所以有一些可能的解决方案。
最简单的方法是引入 seam ,您可以在其中拦截URL的创建。为此,请使用包私有工厂方法封装URL实例:
TestesClass:
URL createUrlFrom(String urlString){
URL url = // some code here
return url;
}
在您的测试类中,您可以使用普通的Mockito来创建CUT的间谍:
@Spy
private CUT cut;
@Before
public static void setup(){
doReturn(myUrlMock).when(cut).createUrlFrom(anyString());
}
@Test
public static void createSpyAndMoclUrl(){
// do call on cut
verify(cut).createUrlFrom(THE_EXPECTED_URL_STRING);
}
答案 1 :(得分:0)
在评论中格式化代码并不容易,因此我会在此处发布我的建议(如果不能正常工作则删除它)
URL urlMock = PowerMockito.mock(URL.class);
HttpURLConnection huc = PowerMockito.mock(HttpURLConnection.class);
PowerMockito.when(urlMock.openConnection()).thenReturn(huc);
PowerMockito.whenNew(URL.class).withArguments(Record.SOURCE_URL).thenReturn(urlMock);