【问题标题】:JUnit @Rule lifecycle interaction with @BeforeJUnit @Rule 生命周期与 @Before 的交互
【发布时间】:2011-12-06 00:51:41
【问题描述】:

我有一些使用 TemporaryFolder @Rule 的 JUnit 测试。他们在@Before 方法中使用TemporaryFolder 来执行一些设置:

@Rule
public TemporaryFolder folder = new TemporaryFolder();

@Before
public void init() {
  folder.newFile("my-file.txt");
}

@Test
public void myTest() { ... }

大多数情况下,这都能完美运行。但是,当使用SpringJUnit4ClassRunner 时,我发现在某些情况下,init() 方法在我的TemporaryFolder 实例中的Statement 被应用之前被调用。因此,当在folder 中使用init() 并且我的文件最终位于工作目录而不是/tmp 时,临时文件夹位置未设置(即:null)。

所以在某些情况下@Before 方法会在规则之前执行,但是,我无法建立明确的模式。我偶尔会在我自己的一些规则实现中看到类似的问题。

有什么方法可以确保在任何设置方法之前应用我的规则语句?

【问题讨论】:

    标签: java junit lifecycle rules


    【解决方案1】:

    在 JUnit 4.10 中,BlockJUnit4ClassRunner(SpringJUnit4ClassRunner 的超类)似乎小心地以规则在任何 @Before 方法之前运行的方式构造语句链。从 JUnit 4.10 开始:

    protected Statement methodBlock(FrameworkMethod method) {
        // ...
        Statement statement= methodInvoker(method, test);
        statement= possiblyExpectingExceptions(method, test, statement);
        statement= withPotentialTimeout(method, test, statement);
        statement= withBefores(method, test, statement);
        statement= withAfters(method, test, statement);
        statement= withRules(method, test, statement);
        return statement;
    }
    

    JUnit 4.7 似乎以不同的顺序将语句链拼接在一起:

    Statement statement= methodInvoker(method, test);
    statement= possiblyExpectingExceptions(method, test, statement);
    statement= withPotentialTimeout(method, test, statement);
    statement= withRules(method, test, statement);
    statement= withBefores(method, test, statement);
    statement= withAfters(method, test, statement);
    return statement;
    

    spring-test-3.0.5 的父 POM 似乎表明它依赖于 JUnit 4.7。我想知道让它使用更新的 JUnit 是否会有所帮助?

    【讨论】:

    • 很好地找到了@pholser。我正在使用 JUnit 4.8.x,它似乎确实以与 4.10 相同的顺序构建链。但是,methodBlock() 在 SpringJUnit4ClassRunner 中被覆盖,并设置了与 JUnit 4.7 类似的不同顺序。
    【解决方案2】:

    对于它的价值,我使用以下方法作为快速解决方法:

    @Rule
    public TemporaryFolder tmpFolder = new TemporaryFolder() {
        @Override
        protected void before() throws Throwable {
            if (getRoot() == null) {
                super.before();
            }
        }
    
        @Override
        public File newFile(String fileName) throws IOException {
            try {
                before();
            }
            catch (Throwable t) {
                throw new RuntimeException(t.getMessage(), t);
            }
    
            return super.newFile(fileName);
        }
    
        @Override
        public File newFolder(String folderName) {
            try {
                before();
            }
            catch (Throwable t) {
                throw new RuntimeException(t.getMessage(), t);
            }
    
            return super.newFolder(folderName);
        }
    };
    

    这确保TemporaryFolder 被正确初始化,无论@Before 方法是在规则之前还是之后运行。

    【讨论】:

      猜你喜欢
      • 2017-08-28
      • 2012-06-03
      • 2013-08-31
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多