1 package uk.org.lidalia.slf4jtest; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 7 import org.junit.After; 8 import org.junit.Test; 9 import org.junit.runner.RunWith; 10 import org.powermock.core.classloader.annotations.PrepareForTest; 11 import org.powermock.modules.junit4.PowerMockRunner; 12 13 import uk.org.lidalia.lang.Task; 14 15 import static org.hamcrest.CoreMatchers.is; 16 import static org.hamcrest.CoreMatchers.sameInstance; 17 import static org.junit.Assert.assertThat; 18 import static org.mockito.Matchers.any; 19 import static org.powermock.api.mockito.PowerMockito.doThrow; 20 import static org.powermock.api.mockito.PowerMockito.mock; 21 import static org.powermock.api.mockito.PowerMockito.mockStatic; 22 import static org.powermock.api.mockito.PowerMockito.when; 23 import static uk.org.lidalia.test.ShouldThrow.shouldThrow; 24 25 @RunWith(PowerMockRunner.class) 26 @PrepareForTest(OverridableProperties.class) 27 public class OverridablePropertiesTests { 28 29 private static final String PROPERTY_SOURCE_NAME = "test"; 30 private static final String PROPERTY_IN_BOTH = "bothprop"; 31 private static final String PROPERTY_IN_SYSTEM_PROPS = "sysprop"; 32 33 @After 34 public void resetLoggerFactory() { 35 System.getProperties().remove(PROPERTY_SOURCE_NAME+"."+PROPERTY_IN_BOTH); 36 System.getProperties().remove(PROPERTY_SOURCE_NAME+"."+PROPERTY_IN_SYSTEM_PROPS); 37 } 38 39 @Test 40 public void propertyNotInEither() throws IOException { 41 mockPropertyFileToContain(""); 42 43 final String defaultValue = "sensible_default"; 44 OverridableProperties properties = new OverridableProperties(PROPERTY_SOURCE_NAME); 45 assertThat(properties.getProperty("notpresent", defaultValue), 46 is(defaultValue)); 47 } 48 49 @Test 50 public void propertyInFileNotInSystemProperties() throws IOException { 51 final String propName = "infile"; 52 final String propValue = "file value"; 53 mockPropertyFileToContain(propName + "=" + propValue); 54 55 OverridableProperties properties = new OverridableProperties(PROPERTY_SOURCE_NAME); 56 assertThat(properties.getProperty(propName, "default"), 57 is(propValue)); 58 } 59 60 @Test 61 public void propertyNotInFileInSystemProperties() throws IOException { 62 final String expectedValue = "system value"; 63 mockPropertyFileToContain(""); 64 System.setProperty(PROPERTY_SOURCE_NAME+"."+PROPERTY_IN_SYSTEM_PROPS, expectedValue); 65 66 OverridableProperties properties = new OverridableProperties("test"); 67 assertThat(properties.getProperty(PROPERTY_IN_SYSTEM_PROPS, "default"), 68 is(expectedValue)); 69 } 70 71 @Test 72 public void propertyInBothFileAndSystemProperties() throws IOException { 73 final String expectedValue = "system value"; 74 mockPropertyFileToContain(PROPERTY_IN_BOTH+"=file value"); 75 System.setProperty(PROPERTY_SOURCE_NAME+"."+PROPERTY_IN_BOTH, expectedValue); 76 77 OverridableProperties properties = new OverridableProperties(PROPERTY_SOURCE_NAME); 78 assertThat(properties.getProperty(PROPERTY_IN_BOTH, "default"), 79 is(expectedValue)); 80 } 81 82 @Test 83 public void noPropertyFile() throws IOException { 84 mockPropertyFileInputStreamToBe(null); 85 86 OverridableProperties properties = new OverridableProperties(PROPERTY_SOURCE_NAME); 87 88 final String defaultValue = "sensible_default"; 89 assertThat(properties.getProperty("blah", defaultValue), is(defaultValue)); 90 } 91 92 @Test 93 public void ioExceptionLoadingProperties() throws IOException { 94 final IOException ioException = new IOException(); 95 final InputStream inputStreamMock = mock(InputStream.class); 96 mockPropertyFileInputStreamToBe(inputStreamMock); 97 when(inputStreamMock.read(any(byte[].class))).thenThrow(ioException); 98 99 final IOException actual = shouldThrow(IOException.class, new Task() { 100 @Override 101 public void perform() throws Exception { 102 new OverridableProperties(PROPERTY_SOURCE_NAME); 103 } 104 }); 105 assertThat(actual, is(ioException)); 106 } 107 108 @Test 109 public void ioExceptionClosingPropertyStream() throws IOException { 110 final IOException ioException = new IOException(); 111 final InputStream inputStreamMock = mock(InputStream.class); 112 mockPropertyFileInputStreamToBe(inputStreamMock); 113 doThrow(ioException).when(inputStreamMock).close(); 114 115 116 final IOException actual = shouldThrow(IOException.class, new Task() { 117 @Override 118 public void perform() throws Exception { 119 new OverridableProperties(PROPERTY_SOURCE_NAME); 120 } 121 }); 122 assertThat(actual, is(ioException)); 123 } 124 125 @Test 126 public void ioExceptionLoadingAndClosingPropertyStream() throws IOException { 127 final IOException loadException = new IOException("exception on load"); 128 final IOException closeException = new IOException("exception on close"); 129 final InputStream inputStreamMock = mock(InputStream.class); 130 mockPropertyFileInputStreamToBe(inputStreamMock); 131 when(inputStreamMock.read(any(byte[].class))).thenThrow(loadException); 132 doThrow(closeException).when(inputStreamMock).close(); 133 134 final IOException finalException = shouldThrow(IOException.class, new Task() { 135 @Override 136 public void perform() throws Exception { 137 new OverridableProperties(PROPERTY_SOURCE_NAME); 138 } 139 }); 140 assertThat(finalException, sameInstance(loadException)); 141 assertThat(finalException.getSuppressed(), is(new Throwable[]{closeException})); 142 } 143 144 private void mockPropertyFileToContain(String propertyFileContents) { 145 final ByteArrayInputStream inputStream = new ByteArrayInputStream(propertyFileContents.getBytes()); 146 mockPropertyFileInputStreamToBe(inputStream); 147 } 148 149 private void mockPropertyFileInputStreamToBe(InputStream inputStream) { 150 mockStatic(Thread.class); 151 Thread threadMock = mock(Thread.class); 152 when(Thread.currentThread()).thenReturn(threadMock); 153 ClassLoader classLoaderMock = mock(ClassLoader.class); 154 when(threadMock.getContextClassLoader()).thenReturn(classLoaderMock); 155 156 when(classLoaderMock.getResourceAsStream(PROPERTY_SOURCE_NAME + ".properties")) 157 .thenReturn(inputStream); 158 } 159 }