|
15 | 15 | */ |
16 | 16 | package org.springframework.data.rest.webmvc; |
17 | 17 |
|
| 18 | +import static org.assertj.core.api.Assertions.*; |
18 | 19 | import static org.mockito.ArgumentMatchers.*; |
19 | 20 | import static org.mockito.Mockito.*; |
20 | 21 |
|
21 | 22 | import java.util.ArrayList; |
| 23 | +import java.util.Collection; |
22 | 24 | import java.util.Collections; |
23 | 25 | import java.util.List; |
24 | 26 | import java.util.Optional; |
25 | 27 |
|
26 | 28 | import org.junit.jupiter.api.Test; |
27 | 29 | import org.junit.jupiter.api.extension.ExtendWith; |
| 30 | +import org.mockito.ArgumentCaptor; |
28 | 31 | import org.mockito.Mock; |
29 | 32 | import org.mockito.junit.jupiter.MockitoExtension; |
30 | 33 | import org.springframework.context.ApplicationEventPublisher; |
| 34 | +import org.springframework.data.rest.core.event.BeforeLinkSaveEvent; |
31 | 35 | import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity; |
32 | 36 | import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext; |
33 | 37 | import org.springframework.data.mapping.PersistentProperty; |
@@ -90,9 +94,88 @@ void usesRepositoryInvokerToLookupRelatedInstance() throws Exception { |
90 | 94 | verify(invoker).invokeFindById("some-id"); |
91 | 95 | } |
92 | 96 |
|
| 97 | + @Test // Link-save events must carry the value actually being saved, not the pre-mutation one. |
| 98 | + void publishesLinkSaveEventWithNewSingularReference() throws Exception { |
| 99 | + |
| 100 | + KeyValuePersistentEntity<?, ?> entity = mappingContext.getRequiredPersistentEntity(Sample.class); |
| 101 | + |
| 102 | + ResourceMappings mappings = new PersistentEntitiesResourceMappings( |
| 103 | + new PersistentEntities(Collections.singleton(mappingContext))); |
| 104 | + ResourceMetadata metadata = spy(mappings.getMetadataFor(Sample.class)); |
| 105 | + when(metadata.getSupportedHttpMethods()).thenReturn(AllSupportedHttpMethods.INSTANCE); |
| 106 | + |
| 107 | + RepositoryPropertyReferenceController controller = new RepositoryPropertyReferenceController(repositories, |
| 108 | + invokerFactory); |
| 109 | + controller.setApplicationEventPublisher(publisher); |
| 110 | + |
| 111 | + Sample owner = new Sample(); |
| 112 | + owner.reference = new Reference(); // the previously linked reference |
| 113 | + Reference newReference = new Reference(); // the one being linked now |
| 114 | + |
| 115 | + doReturn(invoker).when(invokerFactory).getInvokerFor(Reference.class); |
| 116 | + doReturn(Optional.of(owner)).when(invoker).invokeFindById(4711); |
| 117 | + doReturn(Optional.of(newReference)).when(invoker).invokeFindById("new-id"); |
| 118 | + doReturn(owner).when(invoker).invokeSave(any(Object.class)); |
| 119 | + |
| 120 | + RootResourceInformation information = new RootResourceInformation(metadata, entity, invoker); |
| 121 | + CollectionModel<Object> request = CollectionModel.empty(Link.of("/reference/new-id")); |
| 122 | + |
| 123 | + controller.createPropertyReference(information, HttpMethod.PUT, request, 4711, "reference"); |
| 124 | + |
| 125 | + assertThat(captureLinkSaveEvent().getLinked()).isSameAs(newReference); |
| 126 | + } |
| 127 | + |
| 128 | + @Test // Link-save events must carry the value actually being saved, not the pre-mutation one. |
| 129 | + void publishesLinkSaveEventWithReplacedCollection() throws Exception { |
| 130 | + |
| 131 | + KeyValuePersistentEntity<?, ?> entity = mappingContext.getRequiredPersistentEntity(Sample.class); |
| 132 | + |
| 133 | + ResourceMappings mappings = new PersistentEntitiesResourceMappings( |
| 134 | + new PersistentEntities(Collections.singleton(mappingContext))); |
| 135 | + ResourceMetadata metadata = spy(mappings.getMetadataFor(Sample.class)); |
| 136 | + when(metadata.getSupportedHttpMethods()).thenReturn(AllSupportedHttpMethods.INSTANCE); |
| 137 | + |
| 138 | + RepositoryPropertyReferenceController controller = new RepositoryPropertyReferenceController(repositories, |
| 139 | + invokerFactory); |
| 140 | + controller.setApplicationEventPublisher(publisher); |
| 141 | + |
| 142 | + Sample owner = new Sample(); |
| 143 | + Reference oldReference = new Reference(); |
| 144 | + owner.references.add(oldReference); // the previously linked element |
| 145 | + Reference newReference = new Reference(); // the one replacing it via PUT |
| 146 | + |
| 147 | + doReturn(invoker).when(invokerFactory).getInvokerFor(Reference.class); |
| 148 | + doReturn(Optional.of(owner)).when(invoker).invokeFindById(4711); |
| 149 | + doReturn(Optional.of(newReference)).when(invoker).invokeFindById("new-id"); |
| 150 | + doReturn(owner).when(invoker).invokeSave(any(Object.class)); |
| 151 | + |
| 152 | + RootResourceInformation information = new RootResourceInformation(metadata, entity, invoker); |
| 153 | + CollectionModel<Object> request = CollectionModel.empty(Link.of("/reference/new-id")); |
| 154 | + |
| 155 | + controller.createPropertyReference(information, HttpMethod.PUT, request, 4711, "references"); |
| 156 | + |
| 157 | + @SuppressWarnings("unchecked") |
| 158 | + Collection<Reference> linked = (Collection<Reference>) captureLinkSaveEvent().getLinked(); |
| 159 | + |
| 160 | + assertThat(linked).containsExactly(newReference).doesNotContain(oldReference); |
| 161 | + } |
| 162 | + |
| 163 | + private BeforeLinkSaveEvent captureLinkSaveEvent() { |
| 164 | + |
| 165 | + ArgumentCaptor<Object> events = ArgumentCaptor.forClass(Object.class); |
| 166 | + verify(publisher, atLeastOnce()).publishEvent(events.capture()); |
| 167 | + |
| 168 | + return events.getAllValues().stream() // |
| 169 | + .filter(BeforeLinkSaveEvent.class::isInstance) // |
| 170 | + .map(BeforeLinkSaveEvent.class::cast) // |
| 171 | + .findFirst() // |
| 172 | + .orElseThrow(() -> new AssertionError("No BeforeLinkSaveEvent published")); |
| 173 | + } |
| 174 | + |
93 | 175 | @RestResource |
94 | 176 | static class Sample { |
95 | 177 | @org.springframework.data.annotation.Reference List<Reference> references = new ArrayList<Reference>(); |
| 178 | + @org.springframework.data.annotation.Reference Reference reference; |
96 | 179 | } |
97 | 180 |
|
98 | 181 | @RestResource |
|
0 commit comments