与文件系统中二进制文件交互的方法的java单元测试

与文件系统中二进制文件交互的方法的java单元测试,java,unit-testing,file-io,mocking,junit4,Java,Unit Testing,File Io,Mocking,Junit4,我对java编程很陌生,但我会尽量使用正确的术语,尽量避免误解 我已经找到了一些与我的问题非常相似的问题的答案,但或者我只是看不出它们如何真正适合我的问题,或者它们真的不适合。他们中的一些人使用模拟对象,但我不确定这在我的情况下是正确的选择 一般说明 我需要有一个对象数组,其中的信息是从随机访问的二进制文件加载的。二进制文件的第一个字节是文件的头,它定义了数据在文件中的存储方式,基本上表示一些字段的长度,这些字段有助于计算所需数据在文件中的位置 因此,现在我想测试将被调用的方法,以将UnitLi

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

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

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

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

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

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

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

解决方案选项 第一选项

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

第二种选择

另一个选项是使用助手方法f.i.和@BeforeClass在测试内部为测试创建二进制文件,并使用此临时文件运行测试,然后使用@AfterClass方法删除它

问题 您认为考虑TDD方法的最佳实践是什么?模拟对象真的适合这种情况吗?如果有,是否有针对初学者的基本示例文档

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

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

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

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

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

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

到目前为止,我一直在使用EasyMock进行模拟。我觉得这很容易理解,希望能有所帮助。

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

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

  • 使用mocks:将文件读取代码隐藏在接口方法后面,该接口方法采用
    unitlistement
    并返回字节数组,然后在
    getDataFromBinFile
    中使用该方法。然后,您可以在测试中使用模拟读取器模拟该接口,该读取器只返回一些预定义的字节,而不访问任何文件。(或者,您可以将文件读取逻辑移动到
    UnitListElement
    本身,因为现在它似乎是一个POD类。)
  • 无模拟:更改
    getDataFromBinFile
    的签名,以获取字节数组参数,而不是
    UnitListElement
    。在实际的生产代码中,您可以从
    UnitListElement
    描述的文件位置读取数据,然后将其传递到
    getDataFromBinFile
    。在单元测试中,您可以直接将任何二进制数据传递给它。(注意,在这种情况下,将方法重命名为类似于
    getDataFromBytes
    的名称是有意义的)
对于嘲弄,我一直在使用EasyMock
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>
}
}
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
} 
this.getClass().getResourceAsStream("yourfile.name");