diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/DefaultServiceInstance.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/DefaultServiceInstance.java index 2ed54b9f..2e833460 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/DefaultServiceInstance.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/DefaultServiceInstance.java @@ -26,20 +26,23 @@ import java.util.Objects; * * @author Spencer Gibb * @author Tim Ysewyn + * @author Charu Covindane */ public class DefaultServiceInstance implements ServiceInstance { - private final String instanceId; + private String instanceId; - private final String serviceId; + private String serviceId; - private final String host; + private String host; - private final int port; + private int port; - private final boolean secure; + private boolean secure; - private final Map metadata; + private Map metadata = new LinkedHashMap<>(); + + private URI uri; /** * @param instanceId the id of the instance. @@ -96,6 +99,9 @@ public class DefaultServiceInstance implements ServiceInstance { this(serviceId, host, port, secure, new LinkedHashMap<>()); } + public DefaultServiceInstance() { + } + /** * Creates a URI from the given ServiceInstance's host:port. * @param instance the ServiceInstance. @@ -114,39 +120,64 @@ public class DefaultServiceInstance implements ServiceInstance { @Override public Map getMetadata() { - return this.metadata; + return metadata; } @Override public String getInstanceId() { - return this.instanceId; + return instanceId; } @Override public String getServiceId() { - return this.serviceId; + return serviceId; } @Override public String getHost() { - return this.host; + return host; } @Override public int getPort() { - return this.port; + return port; } @Override public boolean isSecure() { - return this.secure; + return secure; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public void setHost(String host) { + this.host = host; + } + + public void setPort(int port) { + this.port = port; + } + + public void setUri(URI uri) { + this.uri = uri; + this.host = this.uri.getHost(); + this.port = this.uri.getPort(); + String scheme = this.uri.getScheme(); + if ("https".equals(scheme)) { + this.secure = true; + } } @Override public String toString() { - return "DefaultServiceInstance{" + "instanceId='" + this.instanceId + '\'' + ", serviceId='" + this.serviceId - + '\'' + ", host='" + this.host + '\'' + ", port=" + this.port + ", secure=" + this.secure - + ", metadata=" + this.metadata + '}'; + return "DefaultServiceInstance{" + "instanceId='" + instanceId + '\'' + ", serviceId='" + serviceId + '\'' + + ", host='" + host + '\'' + ", port=" + port + ", secure=" + secure + ", metadata=" + metadata + '}'; } @Override @@ -158,14 +189,14 @@ public class DefaultServiceInstance implements ServiceInstance { return false; } DefaultServiceInstance that = (DefaultServiceInstance) o; - return this.port == that.port && this.secure == that.secure && Objects.equals(this.instanceId, that.instanceId) - && Objects.equals(this.serviceId, that.serviceId) && Objects.equals(this.host, that.host) - && Objects.equals(this.metadata, that.metadata); + return port == that.port && secure == that.secure && Objects.equals(instanceId, that.instanceId) + && Objects.equals(serviceId, that.serviceId) && Objects.equals(host, that.host) + && Objects.equals(metadata, that.metadata); } @Override public int hashCode() { - return Objects.hash(this.instanceId, this.serviceId, this.host, this.port, this.secure, this.metadata); + return Objects.hash(instanceId, serviceId, host, port, secure, metadata); } } diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClient.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClient.java index f63d5ad4..cd9c1968 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClient.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClient.java @@ -19,9 +19,9 @@ package org.springframework.cloud.client.discovery.simple; import java.util.ArrayList; import java.util.List; +import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties.SimpleServiceInstance; /** * A {@link org.springframework.cloud.client.discovery.DiscoveryClient} that will use the @@ -29,6 +29,7 @@ import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperti * * @author Biju Kunjummen * @author Olga Maciaszek-Sharma + * @author Charu Covindane */ public class SimpleDiscoveryClient implements DiscoveryClient { @@ -46,9 +47,8 @@ public class SimpleDiscoveryClient implements DiscoveryClient { @Override public List getInstances(String serviceId) { List serviceInstances = new ArrayList<>(); - List serviceInstanceForService = this.simpleDiscoveryProperties.getInstances() + List serviceInstanceForService = this.simpleDiscoveryProperties.getInstances() .get(serviceId); - if (serviceInstanceForService != null) { serviceInstances.addAll(serviceInstanceForService); } diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientAutoConfiguration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientAutoConfiguration.java index 417a12ff..afcf9a02 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientAutoConfiguration.java @@ -16,8 +16,6 @@ package org.springframework.cloud.client.discovery.simple; -import java.net.URI; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfigureBefore; @@ -37,6 +35,7 @@ import org.springframework.core.annotation.Order; * Spring Boot auto-configuration for simple properties-based discovery client. * * @author Biju Kunjummen + * @author Charu Covindane */ @Configuration(proxyBeanMethods = false) @AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class }) @@ -65,8 +64,8 @@ public class SimpleDiscoveryClientAutoConfiguration implements ApplicationListen public SimpleDiscoveryProperties simpleDiscoveryProperties( @Value("${spring.application.name:application}") String serviceId) { simple.getLocal().setServiceId(serviceId); - simple.getLocal().setUri( - URI.create("http://" + this.inet.findFirstNonLoopbackHostInfo().getHostname() + ":" + findPort())); + simple.getLocal().setHost(inet.findFirstNonLoopbackHostInfo().getHostname()); + simple.getLocal().setPort(findPort()); return simple; } @@ -80,18 +79,18 @@ public class SimpleDiscoveryClientAutoConfiguration implements ApplicationListen if (port > 0) { return port; } - if (this.server != null && this.server.getPort() != null && this.server.getPort() > 0) { - return this.server.getPort(); + if (server != null && server.getPort() != null && server.getPort() > 0) { + return server.getPort(); } return 8080; } @Override public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) { - this.port = webServerInitializedEvent.getWebServer().getPort(); - if (this.port > 0) { - simple.getLocal().setUri( - URI.create("http://" + this.inet.findFirstNonLoopbackHostInfo().getHostname() + ":" + this.port)); + port = webServerInitializedEvent.getWebServer().getPort(); + if (port > 0) { + simple.getLocal().setHost(inet.findFirstNonLoopbackHostInfo().getHostname()); + simple.getLocal().setPort(port); } } diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryProperties.java index ae826d27..18eba713 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryProperties.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryProperties.java @@ -25,6 +25,7 @@ import java.util.Map; import javax.annotation.PostConstruct; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; @@ -38,31 +39,32 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; * @author Biju Kunjummen * @author Olga Maciaszek-Sharma * @author Tim Ysewyn + * @author Charu Covindane */ @ConfigurationProperties(prefix = "spring.cloud.discovery.client.simple") public class SimpleDiscoveryProperties { - private Map> instances = new HashMap<>(); + private Map> instances = new HashMap<>(); /** * The properties of the local instance (if it exists). Users should set these * properties explicitly if they are exporting data (e.g. metrics) that need to be * identified by the service instance. */ - private SimpleServiceInstance local = new SimpleServiceInstance(); + private DefaultServiceInstance local = new DefaultServiceInstance(null, null, null, 0, false); private int order = DiscoveryClient.DEFAULT_ORDER; - public Map> getInstances() { + public Map> getInstances() { return this.instances; } - public void setInstances(Map> instances) { + public void setInstances(Map> instances) { this.instances = instances; } - public SimpleServiceInstance getLocal() { + public DefaultServiceInstance getLocal() { return this.local; } @@ -77,15 +79,22 @@ public class SimpleDiscoveryProperties { @PostConstruct public void init() { for (String key : this.instances.keySet()) { - for (SimpleServiceInstance instance : this.instances.get(key)) { + for (DefaultServiceInstance instance : this.instances.get(key)) { instance.setServiceId(key); } } } + public void setInstance(String serviceId, String host, int port) { + local = new DefaultServiceInstance(null, serviceId, host, port, false); + } + /** * Basic implementation of {@link ServiceInstance}. + * + * @deprecated in favor of {@link DefaultServiceInstance} */ + @Deprecated public static class SimpleServiceInstance implements ServiceInstance { /** diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryClientAutoConfiguration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryClientAutoConfiguration.java index d845def1..aa77186d 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryClientAutoConfiguration.java @@ -16,8 +16,6 @@ package org.springframework.cloud.client.discovery.simple.reactive; -import java.net.URI; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.actuate.health.ReactiveHealthIndicator; @@ -44,6 +42,7 @@ import org.springframework.core.annotation.Order; * Spring Boot auto-configuration for simple properties-based reactive discovery client. * * @author Tim Ysewyn + * @author Charu Covindane * @since 2.2.0 */ @Configuration(proxyBeanMethods = false) @@ -70,8 +69,8 @@ public class SimpleReactiveDiscoveryClientAutoConfiguration implements Applicati @Bean public SimpleReactiveDiscoveryProperties simpleReactiveDiscoveryProperties() { simple.getLocal().setServiceId(serviceId); - simple.getLocal() - .setUri(URI.create("http://" + inet.findFirstNonLoopbackHostInfo().getHostname() + ":" + findPort())); + simple.getLocal().setHost(inet.findFirstNonLoopbackHostInfo().getHostname()); + simple.getLocal().setPort(findPort()); return simple; } @@ -95,8 +94,8 @@ public class SimpleReactiveDiscoveryClientAutoConfiguration implements Applicati public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) { port = webServerInitializedEvent.getWebServer().getPort(); if (port > 0) { - simple.getLocal() - .setUri(URI.create("http://" + inet.findFirstNonLoopbackHostInfo().getHostname() + ":" + port)); + simple.getLocal().setHost(inet.findFirstNonLoopbackHostInfo().getHostname()); + simple.getLocal().setPort(port); } } diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryProperties.java index 7c6f7efc..72527e8f 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryProperties.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryProperties.java @@ -27,6 +27,7 @@ import javax.annotation.PostConstruct; import reactor.core.publisher.Flux; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; @@ -40,19 +41,20 @@ import static java.util.Collections.emptyList; * {@link org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient}. * * @author Tim Ysewyn + * @author Charu Covindane * @since 2.2.0 */ @ConfigurationProperties(prefix = "spring.cloud.discovery.client.simple") public class SimpleReactiveDiscoveryProperties { - private Map> instances = new HashMap<>(); + private Map> instances = new HashMap<>(); /** * The properties of the local instance (if it exists). Users should set these * properties explicitly if they are exporting data (e.g. metrics) that need to be * identified by the service instance. */ - private SimpleServiceInstance local = new SimpleServiceInstance(); + private DefaultServiceInstance local = new DefaultServiceInstance(); private int order = DiscoveryClient.DEFAULT_ORDER; @@ -60,15 +62,15 @@ public class SimpleReactiveDiscoveryProperties { return Flux.fromIterable(instances.getOrDefault(service, emptyList())); } - Map> getInstances() { + Map> getInstances() { return instances; } - public void setInstances(Map> instances) { + public void setInstances(Map> instances) { this.instances = instances; } - public SimpleServiceInstance getLocal() { + public DefaultServiceInstance getLocal() { return this.local; } @@ -83,7 +85,7 @@ public class SimpleReactiveDiscoveryProperties { @PostConstruct public void init() { for (String key : this.instances.keySet()) { - for (SimpleServiceInstance instance : this.instances.get(key)) { + for (DefaultServiceInstance instance : this.instances.get(key)) { instance.setServiceId(key); } } @@ -92,6 +94,7 @@ public class SimpleReactiveDiscoveryProperties { /** * Basic implementation of {@link ServiceInstance}. */ + @Deprecated public static class SimpleServiceInstance implements ServiceInstance { /** diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientTests.java index a5ffaf62..00f84cc9 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientTests.java @@ -25,13 +25,14 @@ import java.util.Map; import org.junit.Before; import org.junit.Test; +import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties.SimpleServiceInstance; import static org.assertj.core.api.BDDAssertions.then; /** * @author Biju Kunjummen + * @author Charu Covindane */ public class SimpleDiscoveryClientTests { @@ -41,9 +42,9 @@ public class SimpleDiscoveryClientTests { public void setUp() { SimpleDiscoveryProperties simpleDiscoveryProperties = new SimpleDiscoveryProperties(); - Map> map = new HashMap<>(); - SimpleServiceInstance service1Inst1 = new SimpleServiceInstance(URI.create("http://host1:8080")); - SimpleServiceInstance service1Inst2 = new SimpleServiceInstance(URI.create("https://host2:8443")); + Map> map = new HashMap<>(); + DefaultServiceInstance service1Inst1 = new DefaultServiceInstance(null, null, "host1", 8080, false); + DefaultServiceInstance service1Inst2 = new DefaultServiceInstance(null, null, "host2", 8443, true); map.put("service1", Arrays.asList(service1Inst1, service1Inst2)); simpleDiscoveryProperties.setInstances(map); simpleDiscoveryProperties.init(); diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryClientTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryClientTests.java index 50fbf545..ba2d33aa 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryClientTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/reactive/SimpleReactiveDiscoveryClientTests.java @@ -16,7 +16,6 @@ package org.springframework.cloud.client.discovery.simple.reactive; -import java.net.URI; import java.util.Arrays; import org.junit.jupiter.api.BeforeEach; @@ -24,21 +23,22 @@ import org.junit.jupiter.api.Test; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; +import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; -import org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryProperties.SimpleServiceInstance; import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; /** * @author Tim Ysewyn + * @author Charu Covindane */ public class SimpleReactiveDiscoveryClientTests { - private final SimpleServiceInstance service1Inst1 = new SimpleServiceInstance(URI.create("http://host1:8080")); + private final DefaultServiceInstance service1Inst1 = new DefaultServiceInstance(null, null, "host1", 8080, false); - private final SimpleServiceInstance service1Inst2 = new SimpleServiceInstance(URI.create("https://host2:8443")); + private final DefaultServiceInstance service1Inst2 = new DefaultServiceInstance(null, null, "host2", 8443, true); private SimpleReactiveDiscoveryClient client; diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerExchangeFilterFunctionTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerExchangeFilterFunctionTests.java index 3297f6f0..cf76b5d3 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerExchangeFilterFunctionTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerExchangeFilterFunctionTests.java @@ -37,6 +37,7 @@ import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @@ -64,6 +65,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen * Tests for {@link ReactorLoadBalancerExchangeFilterFunction}. * * @author Olga Maciaszek-Sharma + * @author Charu Covindane */ @SuppressWarnings("ConstantConditions") @SpringBootTest(webEnvironment = RANDOM_PORT) @@ -86,13 +88,13 @@ class ReactorLoadBalancerExchangeFilterFunctionTests { @BeforeEach void setUp() { - SimpleDiscoveryProperties.SimpleServiceInstance instance = new SimpleDiscoveryProperties.SimpleServiceInstance(); + DefaultServiceInstance instance = new DefaultServiceInstance(); instance.setServiceId("testservice"); instance.setUri(URI.create("http://localhost:" + this.port)); - SimpleDiscoveryProperties.SimpleServiceInstance instanceWithNoLifecycleProcessors = new SimpleDiscoveryProperties.SimpleServiceInstance(); + DefaultServiceInstance instanceWithNoLifecycleProcessors = new DefaultServiceInstance(); instanceWithNoLifecycleProcessors.setServiceId("serviceWithNoLifecycleProcessors"); instanceWithNoLifecycleProcessors.setUri(URI.create("http://localhost:" + this.port)); - this.properties.getInstances().put("testservice", Collections.singletonList(instance)); + properties.getInstances().put("testservice", Collections.singletonList(instance)); properties.getInstances().put("serviceWithNoLifecycleProcessors", Collections.singletonList(instanceWithNoLifecycleProcessors)); } diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClientTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClientTests.java index 251dccdb..448ee692 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClientTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClientTests.java @@ -17,7 +17,6 @@ package org.springframework.cloud.loadbalancer.blocking.client; import java.io.IOException; -import java.net.URI; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -32,6 +31,7 @@ import reactor.core.publisher.Mono; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties; @@ -60,6 +60,7 @@ import static org.assertj.core.api.Assertions.fail; * Tests for {@link BlockingLoadBalancerClient}. * * @author Olga Maciaszek-Sharma + * @author Charu Covindane */ @SpringBootTest class BlockingLoadBalancerClientTests { @@ -78,8 +79,8 @@ class BlockingLoadBalancerClientTests { @BeforeEach void setUp() { - properties.getInstances().put("myservice", Collections.singletonList( - new SimpleDiscoveryProperties.SimpleServiceInstance(URI.create("https://test.example:9999")))); + DefaultServiceInstance serviceInstance = new DefaultServiceInstance(null, null, "test.example", 9999, true); + properties.getInstances().put("myservice", Collections.singletonList(serviceInstance)); } @Test