Java JUnit预期异常未按预期工作

Java JUnit预期异常未按预期工作,java,junit,Java,Junit,我试图在ActionListener中测试一个私有方法。如果传递了无效url,则该方法应引发异常: 以下是我的测试代码: @Rule public ExpectedException expectedException = ExpectedException.none(); Map<JLabel, JTextField> inputs; ActionListener listener; AddStationWindow window; ArrayList<Station>

我试图在ActionListener中测试一个私有方法。如果传递了无效url,则该方法应引发异常: 以下是我的测试代码:

@Rule
public ExpectedException expectedException = ExpectedException.none();
Map<JLabel, JTextField> inputs;
ActionListener listener;
AddStationWindow window;
ArrayList<Station> stationsToDelete;

@Before
public void setUp() throws IllegalAccessException, NoSuchFieldException, 
InstantiationException, SQLException, ClassNotFoundException {
inputs = new HashMap<JLabel, JTextField>();
window = new AddStationWindow();
stationsToDelete = new ArrayList<>();
InitializeH2Database.initialiteDatabase();

}

@Test
public void saveStation() throws NoSuchFieldException, 
IllegalAccessException, MalformedURLException, NoSuchMethodException, 
InvocationTargetException {
  Field f = window.getClass().getDeclaredField("inputElements");
  f.setAccessible(true);
  LinkedHashMap<JLabel, JTextField> inputs = (LinkedHashMap<JLabel, 
  JTextField>) f.get(window);
  Field f2 = window.getClass().getDeclaredField("save");
  f2.setAccessible(true);
  JButton saveButton = (JButton) f2.get(window);
  inputs.get(window.getInputLabels().get(0)).setText("Testsender");
  inputs.get((window.getInputLabels().get(1))).setText("asdasdsa");
  ActionListener listener = saveButton.getActionListeners()[0];
  Method m = listener.getClass().getDeclaredMethod("saveStation");
  m.setAccessible(true);
  m.invoke(listener);
  expectedException.expect(MalformedURLException.class);
}


@After
public void tearDown() {
stationsToDelete.forEach(s -> 
H2DatabaseConnector.getInstance().deleteStation(s));
}
@规则
public ExpectedException ExpectedException=ExpectedException.none();
地图输入;
动作聆听者;
AddStationWindow窗口;
ArrayList stationsToDelete;
@以前
public void setUp()引发IllegaAccessException,NoSuchFieldException,
实例化异常、SQLException、ClassNotFoundException{
输入=新的HashMap();
window=新的AddStationWindow();
stationsToDelete=新的ArrayList();
InitializeH2Database.initialiteDatabase();
}
@试验
public void saveStation()引发NoSuchFieldException,
IllegalAccessException、MalleformDurException、NoSuchMethodException、,
调用目标异常{
字段f=window.getClass().getDeclaredField(“inputElements”);
f、 setAccessible(true);
LinkedHashMap输入=(LinkedHashMap)f.get(窗口);
字段f2=window.getClass().getDeclaredField(“保存”);
f2.可访问设置(真);
jbuttonsavebutton=(JButton)f2.get(窗口);
inputs.get(window.getInputLabels().get(0)).setText(“Testsender”);
inputs.get((window.getInputLabels().get(1)).setText(“asdasdsa”);
ActionListener=saveButton.getActionListeners()[0];
方法m=listener.getClass().getDeclaredMethod(“存储站”);
m、 setAccessible(true);
m、 调用(监听器);
expectedException.expect(MalformedUrlexException.class);
}
@之后
公共无效拆卸(){
stationsToDelete.forEach(s->
H2DatabaseConnector.getInstance().deleteStation);
}
这是ActionListener中经过测试的方法:

private boolean saveStation() {
List<JLabel> keys = new ArrayList<>();
for (Map.Entry<JLabel, JTextField> inputElement : inputElements.entrySet()) {
    keys.add(inputElement.getKey());
}
String stationName = inputElements.get(keys.get(0)).getText();
String urlString = inputElements.get(keys.get(1)).getText();
URL stationURL = null;
try {
    stationURL = new URL(urlString);
} catch (MalformedURLException e) {
    JOptionPane.showMessageDialog(window, "Invalid URL!", "URL 
    not valid", JOptionPane.ERROR_MESSAGE);
    e.printStackTrace();
    return false;
}
Station s = new Station(stationName, stationURL);
if (checkStation(s)) {
    return WebradioPlayer.addStation(s);
}
return false;
}
private boolean存储站(){
列表键=新的ArrayList();
对于(Map.Entry inputElement:inputElements.entrySet()){
add(inputElement.getKey());
}
String stationName=inputElements.get(key.get(0)).getText();
字符串urlString=inputElements.get(key.get(1)).getText();
URL stationURL=null;
试一试{
stationURL=新URL(urlString);
}捕获(格式错误){
JOptionPane.showMessageDialog(窗口,“无效URL!”,“URL
无效”,作业窗格。错误消息);
e、 printStackTrace();
返回false;
}
车站s=新车站(车站名称,车站URL);
如果(检查站){
返回WebradioPlayer.addStation;
}
返回false;
}
如果我运行测试,我可以看到堆栈tarce显示格式错误的url异常,并显示消息no protocol:'asdasdsa',但测试失败。
有人能解释一下为什么吗?JUnit版本是4。

在调用实际引发异常的代码之前,必须设置预期的异常

而不是

@Test
public void saveStation() throws ... {
    // code here
    expectedException.expect(MalformedURLException.class);
}
您应该将测试方法编写为

@Test
public void saveStation() throws ... {
    expectedException.expect(MalformedURLException.class);
    // code here
}

此外,如果确实希望引发异常,则必须更改方法
存储站
,以不抑制异常。有关更多详细信息,请参阅@Leviand的答案。

您的测试失败,因为您希望引发异常(您说的无效url异常),但您正在将该异常包装到一个try-catch中,然后您正在打印stacktrace

try {
    stationURL = new URL(urlString);
} catch (MalformedURLException e) {
    JOptionPane.showMessageDialog(window, "Invalid URL!", "URL 
    not valid", JOptionPane.ERROR_MESSAGE);
    e.printStackTrace();
    return false;
}
您必须在捕获中添加trown声明,或者根本不捕获它,即:

} catch (MalformedURLException e) {
    JOptionPane.showMessageDialog(window, "Invalid URL!", "URL 
    not valid", JOptionPane.ERROR_MESSAGE);
    e.printStackTrace();
    throw new MalformedURLException(e);
}
并将抛出信息添加到方法中

private boolean saveStation() throws MalformedURLException{

我想检查异常是否被抛出和捕获,但我不想让她通过方法签名中的参数获取“外部”。有没有机会做到这一点?如果你想在junit测试中检查它,获得它的唯一方法是这样的:如果他从来没有联系到他,他就不会意识到异常:)但是有了mockito,我可以保证调用catch块,对吗?有了mockito,你可以测试catch块的效果。验证catch块所做的更改是否实际发生。