package io.muoncore.spring.e2e;
import io.muoncore.protocol.reactivestream.server.PublisherLookup;
import io.muoncore.protocol.reactivestream.server.ReactiveStreamServerHandlerApi;
import io.muoncore.spring.Person;
import io.muoncore.spring.PersonBuilder;
import io.muoncore.spring.e2e.stream.StreamListenerServiceConfiguration;
import io.muoncore.spring.e2e.stream.StreamSourceServiceConfiguration;
import io.muoncore.spring.model.stream.TestStreamController;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import reactor.core.processor.CancelException;
import reactor.rx.broadcast.Broadcaster;
import java.util.ArrayList;
import java.util.List;
import static org.mockito.Mockito.*;
public class StreamingE2ETest {
private static TestStreamController testControllerDelegatingMock;
private static Broadcaster<Person> personSource;
private static Broadcaster<List<Person>> manyPeopleSource;
private static ReactiveStreamServerHandlerApi reactiveStreamServerApi;
@BeforeClass
public static void setUpContext() throws Exception {
testControllerDelegatingMock = Mockito.mock(TestStreamController.class);
ApplicationContext streamSourceServiceContext = new AnnotationConfigApplicationContext(StreamSourceServiceConfiguration.class);
reactiveStreamServerApi = streamSourceServiceContext.getBean(ReactiveStreamServerHandlerApi.class);
personSource = Broadcaster.create();
manyPeopleSource = Broadcaster.create();
reactiveStreamServerApi.publishSource("personStream", PublisherLookup.PublisherType.HOT, personSource);
reactiveStreamServerApi.publishSource("manyPeopleStream", PublisherLookup.PublisherType.HOT, manyPeopleSource);
ApplicationContext streamListenerServiceContext = new AnnotationConfigApplicationContext(StreamListenerServiceConfiguration.class);
streamListenerServiceContext
.getBean(TestStreamController.class)
.setDelegatingMock(testControllerDelegatingMock);
}
@Before
public void setUp() throws Exception {
Mockito.reset(testControllerDelegatingMock);
}
@Test
public void emitsSimpleEvent() throws Exception {
Person aPerson = PersonBuilder.aDefaultPerson().build();
personSource.accept(aPerson);
Thread.sleep(100);
verify(testControllerDelegatingMock, times(1)).addPersonEvent(eq(aPerson));
}
@Test
public void emitsListEvent() throws Exception {
List<Person> people = new ArrayList<>();
people.add(PersonBuilder.aDefaultPerson().withName("Mike").build());
people.add(PersonBuilder.aDefaultPerson().withName("Thomas").build());
manyPeopleSource.accept(people);
Thread.sleep(100);
verify(testControllerDelegatingMock, times(1)).manyPeopleEvent(eq(people));
}
@Test(expected = CancelException.class)
public void throwsExceptionIfPublishToNonExistentStream() throws Exception {
Broadcaster<Person> personBroadcaster = Broadcaster.create();
reactiveStreamServerApi.publishSource("the-wrong-source", PublisherLookup.PublisherType.HOT, personBroadcaster);
Person aPerson = PersonBuilder.aDefaultPerson().build();
personBroadcaster.accept(aPerson);
}
@Test
public void reconnectsAfterBroadcasterFails() throws Exception {
final Broadcaster<Person> removePersonStream = Broadcaster.create();
reactiveStreamServerApi.publishSource("removePersonStream", PublisherLookup.PublisherType.HOT, removePersonStream);
Thread.sleep(200);
Person aPerson = PersonBuilder.aDefaultPerson().build();
removePersonStream.accept(aPerson);
Thread.sleep(100);
verify(testControllerDelegatingMock, times(1)).removePersonEvent(eq(aPerson));
}
}