2017-08-18 85 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

相關問題