2016-06-16 4 views
1

Я пытаюсь написать единичный тест для действия «сохранить как» с помощью mockito. Часть этого действия создает и показывает FileDialog, где пользователь может ввести файл для сохранения. Выбор файла - это не то, что я могу автоматизировать, поэтому хочу высмеять FileDialog и высмеять mockedFileDialog.getFiles(), чтобы вернуть файл, который я хочу «сохранить».Mocking защищенный метод родительского класса дает ошибку «имеет защищенный доступ»

Проблема в том, что диалог файла создается в родительском классе моего действия «сохранить как». 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

Mockito не может издеваться окончательные методы. Чтобы иметь доступ к защищенному методу, тестовый класс должен быть в том же пакете, что и AbstractSaveAction. –

+0

Если бы я сделал метод getFileDialog не окончательным, мог бы быть способ его издеваться? – Sumurai8

ответ

1

Предполагая, что вы используете сэм e package и (за комментарий) могут удалить квалификатор final из методов, я бы подумал о добавлении некоторых методов setter protected к тому, что вы можете вводить mocks в 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); 
     // ... 
    } 
} 

, а затем тест выглядит следующим образом:

@Test 
public void performsSaveAsWhenNetHasNoFile() { 
    SaveAsAction saveAsAction = new SaveAsAction(null, null); 
    FileDialog mockFileDialog = mock(FileDialog.class); 
    Controller mockController = mock(Controller.class); 
    Net mockNet = mock(Net.class); 

    NetName normalName = new NormalNetName(""); 
    when(mockNet.getName()).thenReturn(normalName); 

    File file = new File("test.xml"); 
    when(mockFileDialog.getFiles()).thenReturn(new File[]{file}); 

    // these steps are crucial 
    saveAsAction.setFileDialog(mockFileDialog); 
    saveAsAction.setController(mockController); 

    // test 
    saveAsAction.actionPerformed(null); 

    verify(mockController).saveAsFile(file); 
} 
Смежные вопросы