From 7a6dfe3765b471d2c115e2f802f7ffd61bbd05fe Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Mon, 12 Jan 2015 12:19:11 +0100 Subject: [PATCH] Make MBeanServer integration tests more robust This commit overhauls several of the tests that interact with an MBeanServer with the goal of increasing the reliability of these tests. - MBeanClientInterceptorTests now uses JUnit "assumptions" instead of preemptively returning from test methods, thus allowing such methods to be properly marked as "ignored" instead of "passed". - MBeanClientInterceptorTests now uses JUnit's support for expected exceptions where appropriate. - MBeanClientInterceptorTests and RemoteMBeanClientInterceptorTests now use Spring's SocketUtils to find an available TCP port when starting an MBeanServer instead of aborting the tests when the default JMX port is not available. Issue: SPR-12601 --- .../jmx/AbstractMBeanServerTests.java | 22 +++-- .../access/MBeanClientInterceptorTests.java | 99 +++++++------------ .../RemoteMBeanClientInterceptorTests.java | 19 +++- .../ConnectorServerFactoryBeanTests.java | 5 +- ...MBeanServerConnectionFactoryBeanTests.java | 27 ++--- 5 files changed, 80 insertions(+), 92 deletions(-) diff --git a/spring-context/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java b/spring-context/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java index aebfcd917ad..2a408a43a3c 100644 --- a/spring-context/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java @@ -35,14 +35,24 @@ import static org.junit.Assert.*; /** * Note: certain tests throughout this hierarchy require the presence of * the {@code jmxremote_optional.jar} in your classpath. For this reason, these tests are - * run only if {@link TestGroup#JMXMP} is enabled. If you wish to run these tests, follow - * the instructions in the TestGroup class to enable JMXMP tests. If you run into the - * "Unsupported protocol: jmxmp" error, you will need to download the - * - * JMX Remote API 1.0.1_04 Reference Implementation from Oracle and extract + * run only if {@link TestGroup#JMXMP} is enabled. + * + *

If you wish to run these tests, follow the instructions in the TestGroup class to + * enable JMXMP tests (i.e., set the following Java system property: + * {@code -DtestGroups=jmxmp}). + * + *

If you run into the "Unsupported protocol: jmxmp" error, you will need to + * download the JMX + * Remote API 1.0.1_04 Reference Implementation from Oracle and extract * {@code jmxremote_optional.jar} into your classpath, for example in the {@code lib/ext} * folder of your JVM. - * See also EBR-349. + * + *

See also: + *

* * @author Rob Harrop * @author Juergen Hoeller diff --git a/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java b/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java index 9cb588aaaa0..90fb6f9633a 100644 --- a/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * 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 @@ -22,6 +22,7 @@ import java.lang.reflect.Method; import java.net.BindException; import java.util.HashMap; import java.util.Map; + import javax.management.Descriptor; import javax.management.MBeanServerConnection; import javax.management.remote.JMXConnectorServer; @@ -38,10 +39,15 @@ import org.springframework.jmx.export.MBeanExporter; import org.springframework.jmx.export.assembler.AbstractReflectiveMBeanInfoAssembler; import org.springframework.tests.Assume; import org.springframework.tests.TestGroup; +import org.springframework.util.SocketUtils; import static org.junit.Assert.*; +import static org.junit.Assume.*; /** + * To run the tests in the class, set the following Java system property: + * {@code -DtestGroups=jmxmp}. + * * @author Rob Harrop * @author Juergen Hoeller * @author Sam Brannen @@ -85,16 +91,14 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests { @Test public void testProxyClassIsDifferent() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy = getProxy(); assertTrue("The proxy class should be different than the base class", (proxy.getClass() != IJmxTestBean.class)); } @Test public void testDifferentProxiesSameClass() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy1 = getProxy(); IJmxTestBean proxy2 = getProxy(); @@ -104,8 +108,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests { @Test public void testGetAttributeValue() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy1 = getProxy(); int age = proxy1.getAge(); assertEquals("The age should be 100", 100, age); @@ -113,69 +116,43 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests { @Test public void testSetAttributeValue() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy = getProxy(); proxy.setName("Rob Harrop"); assertEquals("The name of the bean should have been updated", "Rob Harrop", target.getName()); } - @Test + @Test(expected = IllegalArgumentException.class) public void testSetAttributeValueWithRuntimeException() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy = getProxy(); - try { - proxy.setName("Juergen"); - fail("Should have thrown IllegalArgumentException"); - } catch (IllegalArgumentException ex) { - // expected - } + proxy.setName("Juergen"); } - @Test + @Test(expected = ClassNotFoundException.class) public void testSetAttributeValueWithCheckedException() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy = getProxy(); - try { - proxy.setName("Juergen Class"); - fail("Should have thrown ClassNotFoundException"); - } catch (ClassNotFoundException ex) { - // expected - } + proxy.setName("Juergen Class"); } - @Test + @Test(expected = IOException.class) public void testSetAttributeValueWithIOException() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy = getProxy(); - try { - proxy.setName("Juergen IO"); - fail("Should have thrown IOException"); - } catch (IOException ex) { - // expected - } + proxy.setName("Juergen IO"); } - @Test + @Test(expected = InvalidInvocationException.class) public void testSetReadOnlyAttribute() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy = getProxy(); - try { - proxy.setAge(900); - fail("Should not be able to write to a read only attribute"); - } catch (InvalidInvocationException ex) { - // success - } + proxy.setAge(900); } @Test public void testInvokeNoArgs() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy = getProxy(); long result = proxy.myOperation(); assertEquals("The operation should return 1", 1, result); @@ -183,34 +160,27 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests { @Test public void testInvokeArgs() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean proxy = getProxy(); int result = proxy.add(1, 2); assertEquals("The operation should return 3", 3, result); } - @Test + @Test(expected = InvalidInvocationException.class) public void testInvokeUnexposedMethodWithException() throws Exception { - if (!runTests) - return; + assumeTrue(runTests); IJmxTestBean bean = getProxy(); - try { - bean.dontExposeMe(); - fail("Method dontExposeMe should throw an exception"); - } catch (InvalidInvocationException desired) { - // success - } + bean.dontExposeMe(); } @Test public void testTestLazyConnectionToRemote() throws Exception { - if (!runTests) - return; - + assumeTrue(runTests); Assume.group(TestGroup.JMXMP); - JMXServiceURL url = new JMXServiceURL("service:jmx:jmxmp://localhost:9876"); + final int port = SocketUtils.findAvailableTcpPort(); + + JMXServiceURL url = new JMXServiceURL("service:jmx:jmxmp://localhost:" + port); JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, getServer()); MBeanProxyFactoryBean factory = new MBeanProxyFactoryBean(); @@ -227,9 +197,8 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests { try { connector.start(); } catch (BindException ex) { - // couldn't bind to local port 9876 - let's skip the remainder of this test - System.out.println("Skipping JMX LazyConnectionToRemote test because binding to local port 9876 failed: " - + ex.getMessage()); + System.out.println("Skipping remainder of JMX LazyConnectionToRemote test because binding to local port [" + + port + "] failed: " + ex.getMessage()); return; } diff --git a/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java b/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java index d610cf9182e..d4ddfe45c9f 100644 --- a/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * 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 @@ -18,6 +18,7 @@ package org.springframework.jmx.access; import java.net.BindException; import java.net.MalformedURLException; + import javax.management.MBeanServerConnection; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; @@ -27,14 +28,25 @@ import javax.management.remote.JMXServiceURL; import org.springframework.tests.Assume; import org.springframework.tests.TestGroup; +import org.springframework.util.SocketUtils; /** + * To run the tests in the class, set the following Java system property: + * {@code -DtestGroups=jmxmp}. + * * @author Rob Harrop * @author Chris Beams + * @author Sam Brannen */ public class RemoteMBeanClientInterceptorTests extends MBeanClientInterceptorTests { - private static final String SERVICE_URL = "service:jmx:jmxmp://localhost:9876"; + private static final int SERVICE_PORT; + private static final String SERVICE_URL; + + static { + SERVICE_PORT = SocketUtils.findAvailableTcpPort(); + SERVICE_URL = "service:jmx:jmxmp://localhost:" + SERVICE_PORT; + } private JMXConnectorServer connectorServer; @@ -50,7 +62,8 @@ public class RemoteMBeanClientInterceptorTests extends MBeanClientInterceptorTes try { this.connectorServer.start(); } catch (BindException ex) { - // skipping tests, server already running at this port + System.out.println("Skipping remote JMX tests because binding to local port [" + + SERVICE_PORT + "] failed: " + ex.getMessage()); runTests = false; } } diff --git a/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java b/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java index 74a3015d76a..3e3f0943227 100644 --- a/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * 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 @@ -36,6 +36,9 @@ import org.springframework.tests.TestGroup; import static org.junit.Assert.*; /** + * To run the tests in the class, set the following Java system property: + * {@code -DtestGroups=jmxmp}. + * * @author Rob Harrop * @author Chris Beams */ diff --git a/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java b/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java index 086ffb694eb..de4746c4e2d 100644 --- a/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,6 @@ import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; -import org.junit.Before; import org.junit.Test; import org.springframework.aop.support.AopUtils; @@ -34,22 +33,22 @@ import org.springframework.util.SocketUtils; import static org.junit.Assert.*; /** + * To run the tests in the class, set the following Java system property: + * {@code -DtestGroups=jmxmp}. + * * @author Rob Harrop * @author Juergen Hoeller + * @author Sam Brannen */ public class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTests { + private final String serviceUrl; - private String serviceUrl; - - - @Before - public void getUrl() { + { int port = SocketUtils.findAvailableTcpPort(9800, 9900); - this.serviceUrl = "service:jmx:jmxmp://localhost:" + port; + this.serviceUrl = "service:jmx:jmxmp://localhost:" + port; } - private JMXServiceURL getJMXServiceUrl() throws MalformedURLException { return new JMXServiceURL(serviceUrl); } @@ -58,7 +57,6 @@ public class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTe return JMXConnectorServerFactory.newJMXConnectorServer(getJMXServiceUrl(), null, getServer()); } - @Test public void testTestValidConnection() throws Exception { Assume.group(TestGroup.JMXMP); @@ -84,15 +82,10 @@ public class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTe } } - @Test + @Test(expected = IllegalArgumentException.class) public void testWithNoServiceUrl() throws Exception { MBeanServerConnectionFactoryBean bean = new MBeanServerConnectionFactoryBean(); - try { - bean.afterPropertiesSet(); - fail("IllegalArgumentException should be raised when no service url is provided"); - } catch (IllegalArgumentException ex) { - // expected - } + bean.afterPropertiesSet(); } @Test