1

我对 java 编程很陌生,但我会尽量使用正确的术语并尽可能避免误解。

我找到了一些与我的问题非常相似的主题的答案,但或者我只是看不出它们如何真正适合我的问题,或者它们真的不适合。其中一些使用模拟对象,但我不确定在我的情况下这是正确的选择。

一般说明

我需要一个对象数组,这些对象的信息是从随机访问的二进制文件中加载的。二进制文件的第一个字节是文件的标题,它定义了数据如何存储在文件中,基本上表示某些字段的长度,这些字段有助于计算文件中所需数据的位置。

所以现在我想测试将调用的方法以将由UnitListElement对象指定的所需数据加载到Unit对象。为此,我只关注对二进制文件的单次读取。

更详细的视图

我有一个名为Unit的 java 类,它有一些属性,比如说a ,*b* 和c此属性的值通过调用getDataFromBinFile的方法加载:

public class Unit{
    public double[] a;
    public double[] b;
    public double[] c;

getDataFromBinFile(UnitListElement element){
    <here loads the data from the binary file with random access>
}
}

从二进制文件加载数据的方法,打开二进制文件并访问二进制文件中所需的数据。要读取的所需数据在UnitListElement对象中指定:

public class UnitListElement{
    public String pathOfFile;
    public int beginToReadAt;  // info related to where the desired data begins
    public int finishReading;  // info related to where the desired data ends
} 

属性beginToReadAtfinishReading时间引用与二进制文件的头一起用于计算要从二进制文件读取的第一个和最后一个字节位置。

所以我需要做的是一个测试,我调用方法getDataFromBinFile(unitListEl)并测试返回的信息是否正确。

解决方案的选项

第一个选项

在一些有类似问题的帖子中建议使用模拟对象。我试图找到有关模拟对象的文档,但我还没有找到任何简单的初学者指南。因此,虽然不太了解模拟对象,但我的印象是不适合这种情况,因为我要测试的是二进制文件的读取,而不仅仅是与其他对象的交互。

第二个选项

另一种选择是使用辅助方法在测试中为测试创建二进制文件,使用@BeforeClass 来创建测试,并使用此临时文件运行测试,然后使用@AfterClass 方法将其删除。

问题

您认为考虑 TDD 方法的最佳实践是什么?模拟对象真的适合这种情况吗?如果他们这样做了,是否有任何包含初学者基本示例的文档?

或者另一方面,文件的创建更适合测试阅读方法?

谢谢

提前非常感谢。

4

4 回答 4

1

模拟可以应用于您的案例,但实际上这里并不是绝对必要的。您所需要的只是将实际数据处理逻辑与getDataFromBinFile从文件中读取字节的代码分离。

您可以通过(至少)两种方式实现这一目标:

  • 使用 mocks:将文件读取代码隐藏在一个接口方法后面,该接口方法接受 aUnitListElement并返回一个字节数组,然后在getDataFromBinFile. 然后你可以在你的测试中使用一个模拟阅读器模拟这个接口,它只返回一些预定义的字节而不访问任何文件。(或者,您可以将文件读取逻辑移动到UnitListElement自身中,因为现在它似乎是一个 POD 类。)
  • 没有模拟:将签名更改getDataFromBinFile为采用字节数组参数而不是UnitListElement. 在您的实际生产代码中,您可以从 描述的文件位置读取数据UnitListElement,然后将其传递给getDataFromBinFile. 在您的单元测试中,您可以直接将任何二进制数据传递给它。(请注意,在这种情况下,将您的方法重命名为类似的名称是有意义的getDataFromBytes。)

对于模拟,到目前为止我一直在使用 EasyMock。我发现它的文档相当容易理解,希望对您有所帮助。

于 2012-05-08T08:45:22.597 回答
0

我在 TDD 方面没有太多经验。测试文件的读/写时不需要使用模拟,最好的选择是拥有一个测试版本的文件,您将在其上运行测试。当您不能轻松地为您的用例创建可测试对象时使用模拟,例如,如果您正在测试与服务器的交互。

于 2012-05-08T08:38:19.000 回答
0

我不喜欢创建测试二进制文件,因为正在读取的文件格式的任何更改都意味着更改测试文件(以及测试)。

由于您遵循 TDD 方法,因此您必须为“UnitListElement”类编写测试,因此对于这种情况,模拟似乎是一个更好的解决方案。您的目标是测试“getDataFromBinFile”方法而不是“UnitListElement”类方法(当前),因此您可以模拟“UnitListElement”类(或由它继承并传递给 getDataFromBinFile 方法的接口)。模拟“UnitListElement”意味着您可以将预定义的或任何特定的返回值返回给类中的任何方法调用,只要在“getDataFromBinFile”方法中访问它。最后,您可以在“getDataFromBinFile”方法中使用来自模拟的返回值,并在执行业务逻辑后断言该方法的返回值。我没有这里

于 2012-05-08T09:05:10.263 回答
0

只需制作一个测试二进制文件。

此过程正在读取文件。所以没有理由担心文件系统。该文件将始终是确定性的(如果您在阅读期间更改了文件,那将是另一个故事)

如果您想在读入对象后对它们进行测试,我建议您在测试中创建它们(除非这很难做到,比如声音文件)

另外,我建议抽象流而不是文件,但我仍然会使用测试文件进行测试。顺便说一句:确保测试文件很小,毕竟这是一个测试。

有些人可能会争辩说“测试不应该命中文件系统”,但你认为 .class 文件是从哪里加载的?

另外,我会通过 java classLoader 获取流

this.getClass().getResourceAsStream("yourfile.name");

快乐的测试!

卢埃林·法尔科

http://www.approvaltests.com

于 2012-05-10T13:38:28.873 回答