你没有指定什么将用作UI?这会是一个GUI应用程序或网络? 这对一般方法有一些影响,但只是提供一些提示,我会分享我的经验。我使用swing做了很多gui应用程序,这将是我的基准。
所以趋势是让你的GUI尽可能的瘦,并把逻辑,只负责显示组件。为了实现这一点,您可以使用像Presentation Model(http://martinfowler.com/eaaDev/PresentationModel.html)或Passive View(http://martinfowler.com/eaaDev/PassiveScreen.html)这样的众所周知的设计模式。
然后您开始测试您的业务逻辑。一般的指导原则是:
- 您不使用外部资源(文件,数据库等),而是用替换它们的Fakes或Mocks为您的测试提供一些固定的输入。
- 您只测试类的行为不依赖的行为
- 尽量避免复杂的输入
- 使用中提到的模式,你可以嘲笑你的视图层和只测试是否看某些方法,其中在synchrronization层称为。
我希望我能帮上忙。如果不让我知道是否有点模糊。如果你能举一个例子,你会如何解决这个问题,以及你对于你的方法有什么担忧,这也是一件好事。
@举例
我没有使用JavaFX经验,所以我会尽量表现出我会怎么做它摇摆。 这个例子假定你知道什么是模拟,它们是什么。
首先让我们弄清楚瘦客户机中最重要的功能是什么。我会去做那样的事情。用户打开xml文件,应用以某种形式显示它。 (形式不重要,它可能是树,它可能是一张桌子或一个网格无论什么,因为它是视图,我现在不在乎)
基本方案将是用户选择一个文件,应用程序打开该文件并解析它,然后显示结果。我们称之为“Open Results”。
初试:
class OpenResultsShould{
@Test
public void loadResults() {
Data fake = mock (Data.class);
ViewInterface view = mock(ViewInterface.class); // mocking view
when(view.getFilename()).thenReturn("file.xml"); // we specify that when getFileName() method of view mock will be called "file.xml" string will be returned.
ApplicationModelInterface appModel = mock(ApplicationModelInterface.class); // mocking app model
when(appModel.getDataForView()).thenReturn(fake);
OpenResultsAction openResults = new OpenResultsAction(view, appModel);
openResults.actionPerformed(new ActionEvent());
verify(view).getFileName(); // checks that view.getFileName was called within actionPerdormed()
verify(appModel).load("file.xml"); // check that appModel.load() with file.xml as parameter was called within actionPerformed()
verify(appModel).getDataForView(); // similar to above
verify(view).loadDataFromModel(fake); // finally I check if loadDataFromModel on view was called.
}
}
这个测试的目的是检查是否OpenResultsAction将做的工作。这里我们没有测试解析的内容以及gui是否有正确的数据。我们测试某些对象的某些方法是否被调用。此测试还指定了操作类,视图和applicationModel之间的契约。这是通过接口完成的。所以你稍后可以提供具体的实现,这将在下一步中进行测试。 然后我会提供实现,我将跳过这个例子尽可能短。
接下来是什么。由于gui不会被测试,我会去ApplicationModel测试。在第一次测试中,我们指定applicationModelInterface应该有方法加载(String filename);我们将测试它是否具体实现。
class ApplicationModelShould{
@Test
public void loadModelFromFile() {
XMLDocument xml = new XMLDocumentFake();
XMLFileLoader xFileLoader = mock(XMLFileLoader.class);
when(xFileLoader.load("file.xml").thenReturn(xml);
ApplicationModelInterface appModel = new ConcreteApplicationModel(new FileLoaderFake());
appModel.load("plik.xml"); // it should call xFileLoader and then parse returned xml document.
doReturn(xml).when(xFileLoader).load("plik.xml"); // verifies if xFileLoader returned xml when appModel.load called it's load method.
Data expectedResult = populateExpectedResults();
assertEquals(appModel.getDataForView().equals(expectedResult));
}
}
什么是XMLDocument?它存储xml文件的内容。它可以表示为文件行的向量。我们的AppModelLoader会将其解析为对象。 XFileLoader是另一个允许我在单元测试中摆脱文件操作的层。在这里它被嘲笑,但在真正的应用程序中,它应该替换为将读入xml文件并返回XMLDocument的somethind。数据是一个将用于存储分析数据的类。如果XML的内容是“<人> <名>汤姆< /名称> <年龄 /年龄> < /人>然后数据会看起来像:
class Data{
private Person person;
Data(Person person){ this.person = person; }
...
};
class Person{
private String name;
private int age;
.... setters, getters and constructors
}
这基本上是它当然需要更多的测试,例如如果view.getFileName()将返回OpenResultsAction中的空字符串(用户在JFileChooser上点击取消),那么我需要验证是否没有其他东西被调用。如果我将所有的类都测试过,那么我会写GUI部分并结合它。
让我知道这是否合理。
感谢您的好评[Luke](http://stackoverflow.com/users/2862100/luke)。我使用有关胖客户端(javafx)的信息编辑了我的问题。有没有办法为javafx应用程序伪造或模拟内容?或者就此而言,这将如何解决摆动应用程序? – Aspirant
我用一个例子编辑了我的答案。它在@Example之后开始 – Luke