/*
* Copyright 2014 Atteo.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.atteo.moonshine.services;
import java.util.List;
import javax.inject.Inject;
import static org.assertj.core.api.Assertions.assertThat;
import org.assertj.core.util.Lists;
import org.atteo.moonshine.ConfigurationException;
import org.junit.Test;
import org.mockito.Mockito;
import com.google.inject.AbstractModule;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.PrivateModule;
import com.google.inject.TypeLiteral;
public class ServicesTest {
@Test
public void shouldFireListeners() throws ConfigurationException {
LifeCycleListener listener = Mockito.mock(LifeCycleListener.class);
try (Services services = Services.Factory.builder().registerListener(listener).build()) {
Mockito.verify(listener).configured(services.getGlobalInjector());
services.start();
Mockito.verify(listener).started();
}
Mockito.verify(listener).stopping();
Mockito.verify(listener).closing();
}
@Test(expected = IllegalStateException.class)
public void shouldFireStopListenerOnError() throws ConfigurationException {
LifeCycleListener listener = Mockito.mock(LifeCycleListener.class);
try (Services services = Services.Factory.builder()
.registerListener(listener)
.configuration(new AbstractService() {
@Override
public void start() {
throw new IllegalStateException("expected");
}
})
.build()) {
Mockito.verify(listener).configured(services.getGlobalInjector());
services.start();
Mockito.verify(listener, Mockito.times(0)).started();
} finally {
Mockito.verify(listener).stopping();
Mockito.verify(listener).closing();
}
}
@Test
public void shouldStartServicesInDependencyOrder() throws ConfigurationException {
class ServiceA extends AbstractService {
boolean started = false;
@Override
public void start() {
started = true;
}
@Override
public void stop() {
started = false;
}
}
class ServiceB extends AbstractService {
@ImportService
private ServiceA serviceA;
@Override
public void start() {
assertThat(serviceA.started).isTrue();
}
@Override
public void stop() {
assertThat(serviceA.started).isTrue();
}
}
try (Services services = Services.Factory.builder()
.configuration(new AbstractService() {
@Override
public Iterable<? extends Service> getSubServices() {
return Lists.newArrayList(new ServiceB(), new ServiceA());
}
})
.build()) {
services.start();
}
}
@Test
public void shouldConfigureCloseInDependencyOrder() throws ConfigurationException {
class ServiceA extends AbstractService {
boolean configured = false;
@Override
public Module configure() {
configured = true;
return null;
}
@Override
public void close() {
configured = false;
}
}
class ServiceB extends AbstractService {
@ImportService
private ServiceA serviceA;
@Override
public Module configure() {
assertThat(serviceA.configured).isTrue();
return null;
}
@Override
public void close() {
assertThat(serviceA.configured).isTrue();
}
}
try (Services services = Services.Factory.builder()
.configuration(new AbstractService() {
@Override
public Iterable<? extends Service> getSubServices() {
return Lists.newArrayList(new ServiceB(), new ServiceA());
}
})
.build()) {
services.start();
}
}
@Test
public void shouldInjectServiceWhenPrivateModuleIsUsed() throws ConfigurationException {
try (Services services = Services.Factory.builder()
.configuration(new AbstractService() {
@Inject
private String helloWorld;
@Override
public Module configure() {
return new PrivateModule() {
@Override
protected void configure() {
bind(String.class).toInstance("Hello World");
}
};
}
})
.build()) {
}
}
@Test
public void shouldInjectRequestInjection() throws ConfigurationException {
class ProviderService extends AbstractService {
@Override
public String getId() {
return "provider";
}
@Override
public Module configure() {
return new AbstractModule() {
@Override
protected void configure() {
bind(String.class).toInstance("Hello World!");
}
};
}
}
class Consumer {
@Inject
public String hello;
}
final Consumer consumer = new Consumer();
class ConsumerService extends AbstractService {
@ImportService
public ProviderService service;
@Override
public Module configure() {
return new AbstractModule() {
@Override
protected void configure() {
requestInjection(consumer);
}
};
}
}
try (Services services = Services.Factory.builder()
.configuration(new AbstractService() {
@Override
public Iterable<? extends Service> getSubServices() {
ProviderService providerService = new ProviderService();
ConsumerService consumerService = new ConsumerService();
consumerService.service = providerService;
return Lists.newArrayList(providerService, consumerService);
}
}).build()) {
assertThat(consumer.hello).isEqualTo("Hello World!");
}
}
@Test
public void shouldStartTwoInstancesOfTheSameServiceWithDifferentId() throws ConfigurationException {
class Service extends AbstractService {
private final String id;
public Service(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
}
try (Services services = Services.Factory.builder()
.configuration(new AbstractService() {
@Override
public Iterable<? extends Service> getSubServices() {
return Lists.newArrayList(new Service("a"), new Service("b"));
}
})
.build()) {
services.start();
}
}
@Test
public void shouldSupportTwoServicesWithTheSameId() throws ConfigurationException {
class Service extends AbstractService {
}
try (Services services = Services.Factory.builder()
.configuration(new AbstractService() {
@Override
public Iterable<? extends Service> getSubServices() {
return Lists.newArrayList(new Service(), new Service());
}
})
.build()) {
services.start();
}
}
@Test
public void shouldBindListOfServices() throws ConfigurationException {
// given
try (Services services = Services.Factory.builder()
.build()) {
// when
List<? extends ServiceInfo> servicesInfo = services.getGlobalInjector()
.getInstance(Key.get(new TypeLiteral<List<? extends ServiceInfo>>() {}));
// then
assertThat(servicesInfo).isNotEmpty();
}
}
}