所有类的模拟URL

时间:2017-03-12 22:54:07

标签: java unit-testing

我有一个使用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;

如何正确模拟我的网址类?

2 个答案:

答案 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);