2017-08-18 115 views
3

目前,每当我需要响应在另一个线程抛出的异常失败的测试,我写的是这样的:失败单元测试,如果一个异常被另一个线程抛出

package com.example; 

import java.util.ArrayList; 
import java.util.List; 
import org.testng.annotations.Test; 

import static java.util.Arrays.asList; 
import static java.util.Collections.synchronizedList; 
import static org.testng.Assert.fail; 

public final class T { 
    @Test 
    public void testFailureFromLambda() throws Throwable { 
    final List<Throwable> errors = synchronizedList(new ArrayList<>()); 

    asList("0", "1", "2").parallelStream().forEach(s -> { 
     try { 
     /* 
     * The actual code under test here. 
     */ 
     throw new Exception("Error " + s); 
     } catch (final Throwable t) { 
     errors.add(t); 
     } 
    }); 

    if (!errors.isEmpty()) { 
     errors.forEach(Throwable::printStackTrace); 

     final Throwable firstError = errors.iterator().next(); 
     fail(firstError.getMessage(), firstError); 
    } 
    } 
} 

一个同步列表可能会被替换为AtomicReference<Throwable>,但通常代码仍然几乎相同。

有什么标准(和更简洁)干什么用任何测试框架提供的Java相同的方式TestNGJUnitHamcrestAssertJ等)?

回答

4

默认情况下,TestNG在从中抛出异常时会使测试方法失败。我相信JUnit也会发生同样的情况,如果它引发一个意外的异常,它会将测试标记为errored

如果您要处理Streams,那么您需要将其包装在RuntimeException变体中,以便Java不会发出抱怨。 TestNG会自动失败测试。

这里有一个例子:

@Test 
public void testFailureFromLambdaRefactored() { 
    asList("0", "1", "2").parallelStream().forEach(s -> { 
     try { 
     /* 
     * The actual code under test here. 
     */ 
      if (s.equals("2")) { 
       throw new Exception("Error " + s); 
      } 
     } catch (final Throwable t) { 
      throw new RuntimeException(t); 
     } 
    }); 
} 

这是对于涉及lambda表达式和流方案。一般来说,如果您想知道从@Test方法中分离出的新线程中发生的异常,那么您需要使用ExecutorService

这里有一个例子:

@Test 
public void testFailureInAnotherThread() throws InterruptedException, ExecutionException { 
    List<String> list = asList("0", "1", "2"); 
    ExecutorService service = Executors.newFixedThreadPool(2); 
    List<Future<Void>> futures = service.invokeAll(Arrays.asList(new Worker(list))); 
    for (Future future : futures) { 
     future.get(); 
    } 

} 

public static class Worker implements Callable<Void> { 
    private List<String> list; 

    public Worker(List<String> list) { 
     this.list = list; 
    } 

    @Override 
    public Void call() throws Exception { 
     for (String s : list) { 
      if (s.equals("2")) { 
       throw new Exception("Error " + s); 
      } 
     } 
     return null; 
    } 
} 
+0

如果我想阻止失败整个测试,并继续软断言,如果有异常软断言一个抛出? – enissay

+0

@enissay - 默认情况下,只有在所有声明都已经过验证之后,'SoftAssertions'才会通过测试。 –

+0

这不是我的经验。也许我做错了。我发布了这个[问题](https://stackoverflow.com/q/46681601/3619769),希望你能帮助我:) – enissay

相关问题