我对Swing应用程序的单元测试有一些问题。
我想做的是将可绘制对象传递给我的JPanel,每次执行此操作时,它都应该重新绘制自身。

对于基本场景而言,已经非常多了,现在进入我的单元测试:

public class GraphicViewImplTest {

    private JFrame frame;
    private GraphicViewImpl view; //This is my JPanel
    private GraphicLineSpy firstGraphicLine;
    private Line firstLine;

    @Before
    public void setUp() throws Exception {
        frame = new JFrame();
        view = new GraphicViewImpl();
        frame.add(view);
        frame.setVisible(true);
        firstLine = new Line();
        firstLine.setStart(new Point(11, 12));
        firstLine.setEnd(new Point(21, 22));
        firstGraphicLine = new GraphicLineSpy(firstLine);
    }

    @Test
    public void whenReceivingLine_shouldPaintLine() {
        view.receiveShape(firstGraphicLine);
        assertTrue(firstGraphicLine.wasPainted());
    }

}


如您所见,我正在将GraphicLineSpy传递给视图。 GraphicLine类基本上是Line类的装饰器,该类知道如何在Swing中绘制线。 GraphicLineSpy覆盖了GraphicLine的paint方法,只是将标志设置为true,因此我可以检查是否调用了paint方法。

现在开始我的GraphicView JPanel的实现:

public class GraphicViewImpl extends JPanel implements GraphicView, Observer {

    protected GraphicViewPresenter presenter;
    protected List<GraphicShape> graphicShapeList = new LinkedList<>();

    @Override
    public void receiveShape(GraphicShape graphicShape) {
        graphicShapeList.add(graphicShape);
        graphicShape.addObserver(this);
        repaint();
    }

    @Override
    public void removeShape(GraphicShape graphicShape) {
        graphicShapeList.remove(graphicShape);
        graphicShape.removeObserver(this);
        repaint();
    }

    public void setPresenter(GraphicViewPresenter presenter) {
        this.presenter = presenter;
    }

    @Override
    public void update() {
        repaint();
    }

    @Override
    public void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);
        for (GraphicShape graphicShape : graphicShapeList)
            graphicShape.paint(graphics);
    }
}


现在,我的问题是,当我运行这些测试时,他们说我的GraphicLine没有涂漆。但是,当我实际运行该程序并添加新的GraphicLine时,它工作得很好,我的所有Shape都被绘制了。我在测试设置中缺少什么吗?

而且,这可能是最重要的部分,我想这并不是每次运行测试时启动整个JFrame的最佳解决方案,所以我想知道如何最好地创建一个不会破坏的测试双整个重画功能。

预先感谢您的任何提示!

最佳答案

我认为您应该专注于测试代码而不是JPanel实现,因此您应该使用Mockito框架(或任何其他框架)来模拟其他依赖项:

public class GraphicViewImplTest {

    @Rule
    public MockitoRule rule = MockitoJUnit.rule();
    @Mock
    private Graphics2D graphics; // not tested dependency
    @Mock
    private GraphicShape firstLine; // not tested dependency

    private GraphicViewImpl view; //This is my JPanel

    @Before
    public void setUp() throws Exception {
        view = spy(new GraphicViewImpl());
        doNothing().when(view).repaint();
    }

    @Test
    public void whenReceivingLine_shouldPaintLine() {
        view.receiveShape(firstGraphicLine);
        verify(view).repaint();
        verify(firstLine,never()).paint(graphics);

        view.paintComponent(graphics);
        verify(firstLine).paint(graphics);
    }
}

07-24 12:39