2017-03-12 28 views
3

我有一个类Record,它使用new URL(Record.SOURCE_URL)。我有一个名为BaseTestController的测试基类。每个其他测试类都会扩展它。我想模拟new URL,因为Record.SOURCE_URL在本地机器上不可用。模拟所有类的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;

如何正确嘲笑我的URL类?

+0

也许这个职位会帮助你:http://stackoverflow.com/questions/35512053/unable-to-mock-url-class-using-powermockito-mockito –

+0

@ÉricRoberge,不幸的是它不。 – Kousha

+0

如果您为使用的任何模拟库添加标签,您可能会得到更多回复。我对Java的嘲笑生态系统不够熟悉,但是[mockito],[powermock],[powermockito]等等都有预先存在的标签,其中大部分我都分辨不清。 –

回答

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); 
2

恕我直言使用PowerMock的是一个臣服于糟糕的设计。它通常表明您未能遵循单一责任模式问题分离。例如:如果URL对象是一切为它最有可能应的代码测试(CUT)作为一个构造函数参数通过了所有测试一样...

而且PowerMock改变你的字节码( CUT)导致测试覆盖工具失效。

对于您的测试类还有一个继承树是一个坏主意。这是因为对于CUT,UnitTests为文档,并且测试基类中的代码隐藏了关于CUT依赖关系的一些重要信息。


所以有一些可能的解决方案。

最简单的方法是引入一个,您可以在其中拦截创建的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); 
}