如何在JUnit中测试IO代码?

发布于 2024-11-16 15:47:30 字数 1258 浏览 4 评论 0原文

我想测试两个服务:

  1. 构建文件名的服务
  2. 将一些数据写入第一个服务提供的文件

中 首先,我正在构建一些复杂的文件结构(例如 {user}/{date}/ {time}/{generateId}.bin)

第二,我将数据写入第一个服务传递的文件(第一个服务调用第二个服务)

如何使用模拟测试这两个服务而不进行任何真正的 IO 交互?

仅举个例子:

第一个服务:

public class DefaultLogService implements LogService
{

    public void log(SomeComplexData data)
    {
        serializer.write(new FileOutputStream(buildComplexFileStructure()), data);
        or
        serializer.write(buildComplexFileStructure(), data);
        or
        serializer.write(new GenericInputEntity(buildComplexFileStructure()), data);
    }

    private ComplextDataSerializer serializer; // mocked in tests
}

第二个服务:

public class DefaultComplexDataSerializer implements ComplexDataSerializer
{

    void write(InputStream stream, SomeComplexData data) {...}
    or
    void write(File file, SomeCompexData data) {...}
    or
    void write(GenericInputEntity entity, SomeComplexData data) {...}

}

在第一种情况下,我需要传递 FileOutputStream 它将创建一个文件(即我无法测试第一个服务)

在第二种情况下,我需要传递 File.OutputStream 。如果我需要测试将写入指定文件的数据,在第二次服务测试中我该怎么办? (我无法测试第二个服务)

在第三种情况下,我认为我需要一些通用的 IO 对象来包装 File. 也许有一些现成的解决方案可以用于此目的?

I'm want to test two services:

  1. service which builds file name
  2. service which writes some data into file provided by 1st service

In first i'm building some complex file structure (just for example {user}/{date}/{time}/{generatedId}.bin)

In second i'm writing data to the file passed by first service (1st service calls 2nd service)

How can I test both services using mocks without making any real IO interractions?

Just for example:

1st service:

public class DefaultLogService implements LogService
{

    public void log(SomeComplexData data)
    {
        serializer.write(new FileOutputStream(buildComplexFileStructure()), data);
        or
        serializer.write(buildComplexFileStructure(), data);
        or
        serializer.write(new GenericInputEntity(buildComplexFileStructure()), data);
    }

    private ComplextDataSerializer serializer; // mocked in tests
}

2nd service:

public class DefaultComplexDataSerializer implements ComplexDataSerializer
{

    void write(InputStream stream, SomeComplexData data) {...}
    or
    void write(File file, SomeCompexData data) {...}
    or
    void write(GenericInputEntity entity, SomeComplexData data) {...}

}

In first case i need to pass FileOutputStream which will create a file (i.e. i can't test 1st service)

In second case i need to pass File. What can i do in 2nd service test if I need to test data which will be written to specified file? (i can't test 2nd service)

In third case i think i need some generic IO object which will wrap File.
Maybe there is some ready-to-use solution for this purpose?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

豆芽 2024-11-23 15:47:30

在第一种情况下,如果您正在测试文件名生成,为什么还要关心文件本身?您不想测试 FileOutputStream。

我假设您的方法看起来像这样:

public File buildComplexFileStructure() {
    // code
}

您的测试看起来像这样:

@Test public void test() throws Exception {
    File expected = <what you expect to be generated>;
    File actual = new DefaultLogService().buildComplexFileStructure();
    assertEquals(expected, actual);
}

如果该方法未公开公开,则只需将其公开给测试(默认或受保护)。

在第二种情况下,您不能将 ByteArrayOutputStream 从测试测试传递到您的方法中,然后验证写入的内容吗? IE:

@Test public void test() throws Exception {
    btye[] expected = <expected data>;
    ByteArrayOutputStream actualStream = new ByteArrayOutputStream();
    new DefaultComplexDataSerializer().write(actualStream, data);
    byte[] actualData = actualStream.toByteArray();
    // compare expected and actualData
}

In the first case, why do you care about the file itself, if you're testing file name generation? You don't want to test FileOutputStream.

I'm assuming your method looks something like this:

public File buildComplexFileStructure() {
    // code
}

Your test would look something like this:

@Test public void test() throws Exception {
    File expected = <what you expect to be generated>;
    File actual = new DefaultLogService().buildComplexFileStructure();
    assertEquals(expected, actual);
}

If that method isn't exposed publicly, then just expose it to the test (default or protected).

In the second case, couldn't you pass a ByteArrayOutputStream from your test test into your method, then verify what was written to it? i.e.:

@Test public void test() throws Exception {
    btye[] expected = <expected data>;
    ByteArrayOutputStream actualStream = new ByteArrayOutputStream();
    new DefaultComplexDataSerializer().write(actualStream, data);
    byte[] actualData = actualStream.toByteArray();
    // compare expected and actualData
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文