单元测试中的模拟文件/文件系统

时间:2015-04-27 05:39:58

标签: java junit mocking

如果设置了属性,我会创建一个目录。现在,每次运行测试时,都会在我的FileSystem中创建目录。我有办法模拟文件/文件系统吗?

待测班级:

@Service("InitializeEnvironment")
public class EnvironmentChecker implements InitializingBean {



    @Value(value="${delivered_dir}")
    private String delivered_dir;

    @Override
    public void afterPropertiesSet() throws Exception {


        if (!StringUtils.isEmpty(delivered_dir)){
            File dir = new File(delivered_dir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
        }
    }
}

单元测试

public class EnvironmentCheckerTest {

    @Test
    public void testMailHostNichtGesetzt() throws Exception{
        EnvironmentChecker environmentChecker = new EnvironmentChecker();
        setValue(environmentChecker, "delivered_dir", "./");

        environmentChecker.afterPropertiesSet();

    }

    private void setValue(Object target, String fieldname, Object value){
        Field field = ReflectionUtils.findField(target.getClass(),fieldname);
        ReflectionUtils.makeAccessible(field);
        ReflectionUtils.setField(field, target, value);     

    }

1 个答案:

答案 0 :(得分:2)

首先,重要的是要问:这个测试的价值是什么?

可能是您简化了示例,但所有afterPropertiesSet()方法都是在磁盘上创建一个目录,这取决于一些非常简单的前置条件。在文件系统上创建目录是副作用,并且(至少在我看来)带有副作用的代码不适合单元测试。

为什么呢?因为副作用是否发生完全超出了应用程序逻辑的范围。它是否实际发生取决于代码控制之外的许多事情 - 顶部的java文件api,一直到实际在生产机器上进行写入的物理磁盘。

我会用另一种方式 - 即使你嘲笑文件系统,你获得了什么?您可以获得将目录写入模拟文件系统的知识,而不是更多。那是什么意思?它有什么价值吗?它是否能让您对系统在生产中的表现如何表现更有信心?

任何这样的代码只产生副作用,只有非常简单(即太简单测试)的业务逻辑,定义副作用是否应该发生,不应该在第一名。它没有任何价值。

如果在您的实际代码中存在确定是否发生副作用的复杂业务逻辑,那么我的建议是将产生副作用的代码抽象到另一个类中。然后,您可以在现有类中轻松模拟它,以测试它周围的“纯粹”业务逻辑。

请让我强调一点,我并不主张不应该对这种副作用进行测试。我只是说单元测试是测试它们的错误方法。相反,请在生产硬件上进行自动(或手动!)集成测试。