我正在尝试使用mockito为“另存为”操作编写单元测试。该操作的一部分是制作并显示FileDialog,用户可以在其中输入要保存的文件。选择一个文件不是我可以自动化的东西,所以我想模拟FileDialog并模拟mockedFileDialog.getFiles()
以返回我想要“保存”的文件。
问题是文件对话框是在我的“另存为”操作的父类中创建的。 when(..)
似乎只适用于嘲讽,但嘲笑我要测试的课程会破坏练习的重点。然后我只测试是否调用方法,这不是很有用。我可以在测试中运行AbstractSaveAction.saveNet(..)
,但这样我无法确定保存操作是否真的有效 - 我只是测试是否有一种方法可以保存一些东西,但是我无法测试如果有一系列事件调用此函数。
以下测试将产生:
SaveActionTest.java:[60,24] getFileDialog(java.lang.String,java.lang.String) has protected access in application.AbstractSaveAction
测试此操作的正确方法是什么?
要测试的代码
public class SaveAsAction extends AbstractSaveAction {
public SaveAsAction(Controller controller, View view) {
super("", "", controller, view);
}
@Override
public void actionPerformed(ActionEvent e) {
saveAsNet();
}
}
public abstract class AbstractSaveAction extends GuiAction {
public AbstractSaveAction(..) {
//...
}
protected final File saveAsFile(FileDialog fileDialog, String extension) {
//...
}
protected final void saveAsNet() {
FileDialog fileDialog = getFileDialog("Save the world", "xml");
File file = saveAsFile(fileDialog, "xml");
saveNet(file);
}
protected final void saveNet(File file) {
try {
controller.saveAsFile(file);
} catch (TicklishPolarBearException e) {
//Panic
}
}
protected final FileDialog getFileDialog(String title, final String extension) {
FileDialog fileDialog = new FileDialog(view, title, FileDialog.SAVE);
fileDialog.setFile("*." + extension);
fileDialog.setFilenameFilter(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith("." + extension);
}
});
return fileDialog;
}
}
测试
@Test
public void performsSaveAsWhenNetHasNoFile()
throws AllKindsOfExceptions {
NetName normalName = new NormalNetName("");
when(mockNet.getName()).thenReturn(normalName);
File file = new File("test.xml");
//This will error out
when(saveAction.getFileDialog("Save the world", "xml")).thenReturn(mockFileDialog);
when(mockFileDialog.getFiles()).thenReturn(new File[]{file});
saveAsAction.actionPerformed(null);
verify(mockController).saveAsFile(file);
}
答案 0 :(得分:1)
假设您使用相同的包并且(每个注释)可以从方法中删除final
限定符,我会考虑添加一些protected
setter方法,以便将mocks注入{{1} }。这有点争议,但它会起作用。
我有一个工作示例,但要点是生产代码中的以下内容:
AbstractSaveAction
然后测试看起来像:
public abstract class AbstractSaveAction extends GuiAction {
// ...
// for tests only. Consider naming as 'testFileDialog' if you prefer
private FileDialog fileDialog = null;
// for tests only
protected void setFileDialog(FileDialog fileDialog) {
this.fileDialog = fileDialog;
}
// for tests only
protected void setController(Controller controller) {
this.controller = controller;
}
protected FileDialog buildFileDialog(String title) {
FileDialog result = null;
if (this.fileDialog != null) {
result = this.fileDialog;
} else {
result = new FileDialog(view, title, FileDialog.SAVE);
}
return result;
}
protected FileDialog getFileDialog(String title, final String extension) {
// This is new. Get a FileDialog, and if in test-mode
// so be it... It is a light-touch.
FileDialog fileDialog = buildFileDialog(title);
// ...
}
}