|
33 | 33 | import com.fasterxml.jackson.databind.node.ArrayNode;
|
34 | 34 | import com.fasterxml.jackson.databind.node.NullNode;
|
35 | 35 | import com.fasterxml.jackson.databind.node.TextNode;
|
| 36 | +import org.junit.jupiter.api.Disabled; |
36 | 37 | import org.junit.jupiter.api.Nested;
|
37 | 38 | import org.junit.jupiter.api.Test;
|
38 | 39 |
|
|
48 | 49 |
|
49 | 50 | import static org.assertj.core.api.Assertions.assertThat;
|
50 | 51 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
| 52 | +import static org.mockito.ArgumentMatchers.any; |
| 53 | +import static org.mockito.ArgumentMatchers.eq; |
| 54 | +import static org.mockito.BDDMockito.doThrow; |
| 55 | +import static org.mockito.BDDMockito.given; |
| 56 | +import static org.mockito.Mockito.mock; |
| 57 | +import static org.mockito.Mockito.times; |
| 58 | +import static org.mockito.Mockito.verify; |
| 59 | +import static org.springframework.expression.spel.SpelMessage.EXCEPTION_DURING_INDEX_READ; |
| 60 | +import static org.springframework.expression.spel.SpelMessage.EXCEPTION_DURING_INDEX_WRITE; |
51 | 61 | import static org.springframework.expression.spel.SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE;
|
52 | 62 | import static org.springframework.expression.spel.SpelMessage.UNABLE_TO_GROW_COLLECTION_UNKNOWN_ELEMENT_TYPE;
|
53 | 63 |
|
@@ -485,7 +495,115 @@ void addingAndRemovingIndexAccessors() {
|
485 | 495 | }
|
486 | 496 |
|
487 | 497 | @Test
|
488 |
| - void indexReadWrite() { |
| 498 | + void noSuitableIndexAccessorResultsInException() { |
| 499 | + StandardEvaluationContext context = new StandardEvaluationContext(); |
| 500 | + assertThat(context.getIndexAccessors()).isEmpty(); |
| 501 | + |
| 502 | + SpelExpressionParser parser = new SpelExpressionParser(); |
| 503 | + Expression expr = parser.parseExpression("[0]"); |
| 504 | + assertThatExceptionOfType(SpelEvaluationException.class) |
| 505 | + .isThrownBy(() -> expr.getValue(context, this)) |
| 506 | + .withMessageEndingWith("Indexing into type '%s' is not supported", getClass().getName()) |
| 507 | + .extracting(SpelEvaluationException::getMessageCode).isEqualTo(INDEXING_NOT_SUPPORTED_FOR_TYPE); |
| 508 | + } |
| 509 | + |
| 510 | + @Test |
| 511 | + void canReadThrowsException() throws Exception { |
| 512 | + StandardEvaluationContext context = new StandardEvaluationContext(); |
| 513 | + RuntimeException exception = new RuntimeException("Boom!"); |
| 514 | + |
| 515 | + IndexAccessor mock = mock(); |
| 516 | + given(mock.canRead(any(), eq(this), any())).willThrow(exception); |
| 517 | + context.addIndexAccessor(mock); |
| 518 | + |
| 519 | + SpelExpressionParser parser = new SpelExpressionParser(); |
| 520 | + Expression expr = parser.parseExpression("[0]"); |
| 521 | + assertThatExceptionOfType(SpelEvaluationException.class) |
| 522 | + .isThrownBy(() -> expr.getValue(context, this)) |
| 523 | + .withMessageEndingWith("A problem occurred while attempting to read index '%d' in '%s'", |
| 524 | + 0, getClass().getName()) |
| 525 | + .withCause(exception) |
| 526 | + .extracting(SpelEvaluationException::getMessageCode).isEqualTo(EXCEPTION_DURING_INDEX_READ); |
| 527 | + |
| 528 | + verify(mock, times(1)).canRead(any(), any(), any()); |
| 529 | + } |
| 530 | + |
| 531 | + @Test |
| 532 | + void readThrowsException() throws Exception { |
| 533 | + StandardEvaluationContext context = new StandardEvaluationContext(); |
| 534 | + RuntimeException exception = new RuntimeException("Boom!"); |
| 535 | + |
| 536 | + IndexAccessor mock = mock(); |
| 537 | + given(mock.canRead(any(), eq(this), any())).willReturn(true); |
| 538 | + given(mock.read(any(), eq(this), any())).willThrow(exception); |
| 539 | + context.addIndexAccessor(mock); |
| 540 | + |
| 541 | + SpelExpressionParser parser = new SpelExpressionParser(); |
| 542 | + Expression expr = parser.parseExpression("[0]"); |
| 543 | + assertThatExceptionOfType(SpelEvaluationException.class) |
| 544 | + .isThrownBy(() -> expr.getValue(context, this)) |
| 545 | + .withMessageEndingWith("A problem occurred while attempting to read index '%d' in '%s'", |
| 546 | + 0, getClass().getName()) |
| 547 | + .withCause(exception) |
| 548 | + .extracting(SpelEvaluationException::getMessageCode).isEqualTo(EXCEPTION_DURING_INDEX_READ); |
| 549 | + |
| 550 | + verify(mock, times(1)).canRead(any(), any(), any()); |
| 551 | + verify(mock, times(1)).read(any(), any(), any()); |
| 552 | + } |
| 553 | + |
| 554 | + @Disabled("Disabled until IndexAccessor#canWrite is honored") |
| 555 | + @Test |
| 556 | + void canWriteThrowsException() throws Exception { |
| 557 | + StandardEvaluationContext context = new StandardEvaluationContext(); |
| 558 | + RuntimeException exception = new RuntimeException("Boom!"); |
| 559 | + |
| 560 | + IndexAccessor mock = mock(); |
| 561 | + // TODO canRead() should not be invoked for this use case. |
| 562 | + given(mock.canRead(any(), eq(this), any())).willReturn(true); |
| 563 | + // TODO canWrite() should be invoked for this use case, but it is currently not. |
| 564 | + given(mock.canWrite(eq(context), eq(this), eq(0))).willThrow(exception); |
| 565 | + context.addIndexAccessor(mock); |
| 566 | + |
| 567 | + SpelExpressionParser parser = new SpelExpressionParser(); |
| 568 | + Expression expr = parser.parseExpression("[0]"); |
| 569 | + assertThatExceptionOfType(SpelEvaluationException.class) |
| 570 | + .isThrownBy(() -> expr.setValue(context, this, 999)) |
| 571 | + .withMessageEndingWith("A problem occurred while attempting to write index '%d' in '%s'", |
| 572 | + 0, getClass().getName()) |
| 573 | + .withCause(exception) |
| 574 | + .extracting(SpelEvaluationException::getMessageCode).isEqualTo(EXCEPTION_DURING_INDEX_WRITE); |
| 575 | + |
| 576 | + verify(mock, times(1)).canWrite(any(), any(), any()); |
| 577 | + } |
| 578 | + |
| 579 | + @Test |
| 580 | + void writeThrowsException() throws Exception { |
| 581 | + StandardEvaluationContext context = new StandardEvaluationContext(); |
| 582 | + RuntimeException exception = new RuntimeException("Boom!"); |
| 583 | + |
| 584 | + IndexAccessor mock = mock(); |
| 585 | + // TODO canRead() should not be invoked for this use case. |
| 586 | + given(mock.canRead(any(), eq(this), any())).willReturn(true); |
| 587 | + given(mock.canWrite(eq(context), eq(this), eq(0))).willReturn(true); |
| 588 | + doThrow(exception).when(mock).write(any(), any(), any(), any()); |
| 589 | + context.addIndexAccessor(mock); |
| 590 | + |
| 591 | + SpelExpressionParser parser = new SpelExpressionParser(); |
| 592 | + Expression expr = parser.parseExpression("[0]"); |
| 593 | + assertThatExceptionOfType(SpelEvaluationException.class) |
| 594 | + .isThrownBy(() -> expr.setValue(context, this, 999)) |
| 595 | + .withMessageEndingWith("A problem occurred while attempting to write index '%d' in '%s'", |
| 596 | + 0, getClass().getName()) |
| 597 | + .withCause(exception) |
| 598 | + .extracting(SpelEvaluationException::getMessageCode).isEqualTo(EXCEPTION_DURING_INDEX_WRITE); |
| 599 | + |
| 600 | + // TODO canWrite() should be invoked for this use case, but it is currently not. |
| 601 | + // verify(mock, times(1)).canWrite(any(), any(), any()); |
| 602 | + verify(mock, times(1)).write(any(), any(), any(), any()); |
| 603 | + } |
| 604 | + |
| 605 | + @Test |
| 606 | + void readAndWriteIndex() { |
489 | 607 | StandardEvaluationContext context = new StandardEvaluationContext();
|
490 | 608 |
|
491 | 609 | ObjectMapper objectMapper = new ObjectMapper();
|
|
0 commit comments