线程中抛出JUnit5检查异常
JUnit5 check exception is thrown in thread
我有这样的服务:
class SomeService{
private final Executor executor = Executors.newFixedThreadPool(10);
void handle(SomeEvent event) {
executor.execute(
() -> {
//... logic omitted
if (isBadCase()) {
throw new RuntimeException("Something bad happen");
}
//... time consuming logic continued
}
);
}
...
//other methods
}
我想测试“badCase”,即 RuntimeException("Something bad happen")
被抛出。
是否可以使用JUnit5实现?
对于“正常”或“notSoBad”的其他情况,我已经实施了变通方法,这只是一个等待周期,以便满足相应情况的某些条件,如下所示:
private void awaitForNormalConditionIsMet(int seconds) {
for (int step = 1; step <= seconds * 40; step++) {
if (normalConditionIsMet()) return;
else {
try {
System.out.println("Waiting for condition - " + (step * 25) + "ms");
Thread.sleep(25);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Assertions.fail();
}
当我有相应的东西需要检查时,这个解决方法很有效。
但是对于“badCase”没有相应的改变,只是抛出异常。
而且我无法从执行程序中提取异常抛出逻辑。
你能帮忙吗?
您可能想要重构代码,尤其是当您的 Runnable
具有更复杂的逻辑时。
如果您将其作为单独的 单元 进行测试,您可以更好地控制它。而且测试更容易,例如:
public class SomeService {
private final Executor executor = Executors.newFixedThreadPool(10);
void handle(SomeEvent event) {
executor.execute(new MyRunnable(event));
}
// This is inner non-static in my example class because isBadCase()
// could be in service. Of course this isBadCase could be anywhere.
public class MyRunnable implements Runnable {
private SomeEvent event;
public MyRunnable(SomeEvent event) {
this.event = event;
}
@Override
public void run() {
if (isBadCase()) {
throw new RuntimeException("Something bad happen");
}
}
}
public boolean isBadCase() {
return false;
}
}
现在线程没有问题了,因为您可以直接在主线程中捕获异常,同时您正在对代码进行更精细的单元测试:
@ExtendWith(MockitoExtension.class)
class SomeServiceTest {
// Spy is because you want to mock normal case for isBadCase = false
// to true so causing the exception to be thrown
@Spy
private SomeService someService;
@Test
void testOk() {
someService.new MyRunnable(new SomeEvent()).run();
}
@Test
void testBadCase() {
Mockito.when(someService.isBadCase()).thenReturn(true);
MyRunnable myRunnable = someService.new MyRunnable(new SomeEvent());
assertThrows(RuntimeException.class, () -> myRunnable.run());
}
}
我有这样的服务:
class SomeService{
private final Executor executor = Executors.newFixedThreadPool(10);
void handle(SomeEvent event) {
executor.execute(
() -> {
//... logic omitted
if (isBadCase()) {
throw new RuntimeException("Something bad happen");
}
//... time consuming logic continued
}
);
}
...
//other methods
}
我想测试“badCase”,即 RuntimeException("Something bad happen")
被抛出。
是否可以使用JUnit5实现?
对于“正常”或“notSoBad”的其他情况,我已经实施了变通方法,这只是一个等待周期,以便满足相应情况的某些条件,如下所示:
private void awaitForNormalConditionIsMet(int seconds) {
for (int step = 1; step <= seconds * 40; step++) {
if (normalConditionIsMet()) return;
else {
try {
System.out.println("Waiting for condition - " + (step * 25) + "ms");
Thread.sleep(25);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Assertions.fail();
}
当我有相应的东西需要检查时,这个解决方法很有效。 但是对于“badCase”没有相应的改变,只是抛出异常。
而且我无法从执行程序中提取异常抛出逻辑。 你能帮忙吗?
您可能想要重构代码,尤其是当您的 Runnable
具有更复杂的逻辑时。
如果您将其作为单独的 单元 进行测试,您可以更好地控制它。而且测试更容易,例如:
public class SomeService {
private final Executor executor = Executors.newFixedThreadPool(10);
void handle(SomeEvent event) {
executor.execute(new MyRunnable(event));
}
// This is inner non-static in my example class because isBadCase()
// could be in service. Of course this isBadCase could be anywhere.
public class MyRunnable implements Runnable {
private SomeEvent event;
public MyRunnable(SomeEvent event) {
this.event = event;
}
@Override
public void run() {
if (isBadCase()) {
throw new RuntimeException("Something bad happen");
}
}
}
public boolean isBadCase() {
return false;
}
}
现在线程没有问题了,因为您可以直接在主线程中捕获异常,同时您正在对代码进行更精细的单元测试:
@ExtendWith(MockitoExtension.class)
class SomeServiceTest {
// Spy is because you want to mock normal case for isBadCase = false
// to true so causing the exception to be thrown
@Spy
private SomeService someService;
@Test
void testOk() {
someService.new MyRunnable(new SomeEvent()).run();
}
@Test
void testBadCase() {
Mockito.when(someService.isBadCase()).thenReturn(true);
MyRunnable myRunnable = someService.new MyRunnable(new SomeEvent());
assertThrows(RuntimeException.class, () -> myRunnable.run());
}
}