├── .travis.yml ├── src ├── main │ ├── resources │ │ └── files │ │ │ └── air_jordan.jpg │ └── java │ │ └── com │ │ └── tacitknowledge │ │ └── jcr │ │ ├── mocking │ │ ├── JcrMockService.java │ │ ├── domain │ │ │ └── PropertyDefinitionMap.java │ │ └── impl │ │ │ └── JsonMockService.java │ │ └── testing │ │ ├── utils │ │ ├── JcrMockingUtils.java │ │ ├── JcrTestingUtils.java │ │ └── PropertyTypeEnum.java │ │ ├── impl │ │ ├── NodeIteratorAdapter.java │ │ ├── PropertyIteratorAdapter.java │ │ └── MockNodeFactory.java │ │ └── NodeFactory.java └── test │ ├── resources │ ├── files │ │ └── air_jordan.jpg │ ├── assets.json │ ├── mock-nodes.json │ └── asset_list.json │ └── java │ └── com │ └── tacitknowledge │ └── jcr │ ├── testing │ ├── utils │ │ ├── JcrTestingUtilsTest.java │ │ ├── PropertyTypeEnumTest.java │ │ └── JcrMockingUtilsTest.java │ └── impl │ │ ├── NodeIteratorAdapterTest.java │ │ ├── PropertyIteratorAdapterTest.java │ │ └── MockNodeFactoryTest.java │ └── mocking │ ├── domain │ └── PropertyDefinitionMapTest.java │ ├── impl │ └── JsonMockingServiceTest.java │ └── JcrMockServiceTest.java ├── .gitignore ├── pom.xml ├── checkstyle.config └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | -------------------------------------------------------------------------------- /src/main/resources/files/air_jordan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tacitknowledge/jcr-mock/HEAD/src/main/resources/files/air_jordan.jpg -------------------------------------------------------------------------------- /src/test/resources/files/air_jordan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tacitknowledge/jcr-mock/HEAD/src/test/resources/files/air_jordan.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ Project Files # 2 | *.iml 3 | *.ipr 4 | *.iws 5 | .idea 6 | 7 | # Maven # 8 | target 9 | 10 | # OSX # 11 | .DS_Store 12 | -------------------------------------------------------------------------------- /src/test/resources/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | digitalAsset : { 3 | name : "air_jordan.jpg", 4 | mimeType : "jpg", 5 | contentType : "photography", 6 | resolution : '300ppi', 7 | binary : { 8 | 'jcr:primaryType' : "nt:file", 9 | "jcr:content" : "type:Binary, value:/files/air_jordan.jpg" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/mocking/JcrMockService.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.mocking; 2 | 3 | import javax.jcr.Node; 4 | import javax.jcr.RepositoryException; 5 | 6 | /** 7 | * @author Daniel Valencia (daniel@tacitknowledge.com) 8 | */ 9 | public interface JcrMockService { 10 | 11 | Node fromString(Node parentNode, String nodeDefinition) throws RepositoryException; 12 | 13 | Node fromString(String jsonNodeStructure) throws RepositoryException; 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/mock-nodes.json: -------------------------------------------------------------------------------- 1 | {ac2d111 : { 2 | binary : { 3 | 'jcr:primaryType' : "nt:file" 4 | }, 5 | trustEntity : "type:String", 6 | view : "type:String" 7 | }, 8 | ac2d112 : { 9 | binary : { 10 | 'jcr:primaryType' : "nt:file" 11 | }, 12 | trustEntity : "type:String", 13 | view : "type:String" 14 | }, 15 | ac2d113 : { 16 | binary : { 17 | 'jcr:primaryType' : "nt:file" 18 | }, 19 | trustEntity : "type:String", 20 | view : "type:String" 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/testing/utils/JcrMockingUtils.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.utils; 2 | 3 | import com.tacitknowledge.jcr.mocking.JcrMockService; 4 | import com.tacitknowledge.jcr.mocking.impl.JsonMockService; 5 | import com.tacitknowledge.jcr.testing.NodeFactory; 6 | import com.tacitknowledge.jcr.testing.impl.MockNodeFactory; 7 | import org.apache.commons.io.IOUtils; 8 | 9 | import javax.jcr.Node; 10 | import javax.jcr.RepositoryException; 11 | import javax.jcr.nodetype.NodeTypeManager; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | 15 | /** 16 | * Utility class for JCR mocking 17 | * 18 | * @author Daniel Valencia (daniel@tacitknowledge.com) 19 | */ 20 | public class JcrMockingUtils 21 | { 22 | 23 | public static Node createNodesFromJsonString(String jsonNodeDefinition) throws RepositoryException, IOException 24 | { 25 | NodeFactory nodeFactory = new MockNodeFactory(); 26 | JcrMockService mockService = new JsonMockService(nodeFactory); 27 | return mockService.fromString(jsonNodeDefinition); 28 | } 29 | 30 | public static Node createNodesFromJsonFile(InputStream assetsJsonFile) throws IOException, RepositoryException 31 | { 32 | String jsonFormattedString = IOUtils.toString(assetsJsonFile); 33 | NodeFactory nodeFactory = new MockNodeFactory(); 34 | JcrMockService mockService = new JsonMockService(nodeFactory); 35 | return mockService.fromString(jsonFormattedString); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/testing/utils/JcrTestingUtils.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.utils; 2 | 3 | import org.junit.Assert; 4 | 5 | import javax.jcr.Property; 6 | import javax.jcr.PropertyType; 7 | import javax.jcr.RepositoryException; 8 | import java.util.Iterator; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | import static org.junit.Assert.assertNotNull; 12 | 13 | public class JcrTestingUtils { 14 | 15 | public static void assertProperty(Property property, int expectedType, Object expectedValue) throws RepositoryException { 16 | assertPropertyType(property, expectedType); 17 | Assert.assertEquals("Expected Empty String", expectedValue, PropertyTypeEnum.fromType(expectedType).getObjectValue(property.getValue())); 18 | } 19 | 20 | public static void assertPropertyType(Property property, int expectedType) throws RepositoryException { 21 | Assert.assertEquals("Expected Type " + PropertyType.nameFromValue(expectedType) + " but got " 22 | + PropertyType.nameFromValue(property.getType()) 23 | , expectedType, property.getType()); 24 | } 25 | 26 | public static void assertIteratorCount(Iterator iterator, int expectedCount) { 27 | int counter = 0; 28 | 29 | while (iterator.hasNext()){ 30 | assertNotNull("Expected a non null node", iterator.next()); 31 | counter++; 32 | } 33 | 34 | assertEquals("Expected 1 node", expectedCount, counter); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/testing/impl/NodeIteratorAdapter.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.impl; 2 | 3 | import org.apache.commons.collections.IteratorUtils; 4 | 5 | import javax.jcr.Node; 6 | import javax.jcr.NodeIterator; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | public class NodeIteratorAdapter implements NodeIterator { 11 | 12 | private int position; 13 | private Iterator iterator; 14 | private List nodeList; 15 | 16 | public NodeIteratorAdapter(Iterator iterator) { 17 | this.nodeList = IteratorUtils.toList(iterator); 18 | this.iterator = nodeList.iterator(); 19 | this.position = 0; 20 | } 21 | 22 | @Override 23 | public Node nextNode() { 24 | Node next = iterator.next(); 25 | removeFromList(1); 26 | return next; 27 | } 28 | 29 | @Override 30 | public void skip(long skipNum) { 31 | removeFromList((int) skipNum); 32 | iterator = nodeList.iterator(); 33 | } 34 | 35 | private void removeFromList(int skipNum) { 36 | int size = nodeList.size(); 37 | nodeList = nodeList.subList(skipNum, size); 38 | position += skipNum; 39 | } 40 | 41 | @Override 42 | public long getSize() { 43 | return nodeList.size(); 44 | } 45 | 46 | @Override 47 | public long getPosition() { 48 | return position; 49 | } 50 | 51 | @Override 52 | public boolean hasNext() { 53 | return iterator.hasNext(); 54 | } 55 | 56 | @Override 57 | public Object next() { 58 | Node next = iterator.next(); 59 | removeFromList(1); 60 | return next; 61 | } 62 | 63 | @Override 64 | public void remove() { 65 | removeFromList(1); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/testing/impl/PropertyIteratorAdapter.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.impl; 2 | 3 | import org.apache.commons.collections.IteratorUtils; 4 | 5 | import javax.jcr.Property; 6 | import javax.jcr.PropertyIterator; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | /** 11 | * Created with IntelliJ IDEA. 12 | * User: alayouni 13 | * Date: 10/21/13 14 | * Time: 10:59 AM 15 | * To change this template use File | Settings | File Templates. 16 | */ 17 | public class PropertyIteratorAdapter implements PropertyIterator { 18 | private int position; 19 | private Iterator iterator; 20 | private List propertyList; 21 | 22 | public PropertyIteratorAdapter(Iterator iterator) { 23 | this.propertyList = IteratorUtils.toList(iterator); 24 | this.iterator = propertyList.iterator(); 25 | this.position = 0; 26 | } 27 | 28 | @Override 29 | public Property nextProperty() { 30 | Property next = iterator.next(); 31 | removeFromList(1); 32 | return next; 33 | } 34 | 35 | @Override 36 | public void skip(long skipNum) { 37 | removeFromList((int) skipNum); 38 | iterator = propertyList.iterator(); 39 | } 40 | 41 | private void removeFromList(int skipNum) { 42 | int size = propertyList.size(); 43 | propertyList = propertyList.subList(skipNum, size); 44 | position += skipNum; 45 | } 46 | 47 | @Override 48 | public long getSize() { 49 | return propertyList.size(); 50 | } 51 | 52 | @Override 53 | public long getPosition() { 54 | return position; 55 | } 56 | 57 | @Override 58 | public boolean hasNext() { 59 | return iterator.hasNext(); 60 | } 61 | 62 | @Override 63 | public Property next() { 64 | Property next = iterator.next(); 65 | removeFromList(1); 66 | return next; 67 | } 68 | 69 | @Override 70 | public void remove() { 71 | removeFromList(1); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/resources/asset_list.json: -------------------------------------------------------------------------------- 1 | { 2 | products : { 3 | 12345 : { 4 | name: 'Air Jordan', 5 | id: '12345', 6 | digitalAssets: { 7 | asset_1 : { 8 | name: 'asset_1', 9 | binary_ref: 'type:Reference, value:123456' 10 | }, 11 | asset_2 : { 12 | name: 'asset_2', 13 | binary_ref: 'type:Reference, value:234567' 14 | }, 15 | asset_3 : { 16 | name: 'asset_3', 17 | binary_ref: 'type:Reference, value:345678' 18 | } 19 | } 20 | } 21 | }, 22 | digitalAssets : { 23 | 123456 : { 24 | id : '123456', 25 | name : "air_jordan.jpg", 26 | mimeType : "jpg", 27 | contentType : "photography", 28 | resolution : '300ppi', 29 | binary : { 30 | 'jcr:primaryType' : "nt:file", 31 | "jcr:content" : "type:Binary, value:/files/air_jordan.jpg" 32 | } 33 | }, 34 | 234567 : { 35 | id : '234567', 36 | name : "air_jordan.jpg", 37 | mimeType : "jpg", 38 | contentType : "photography", 39 | resolution : '300ppi', 40 | binary : { 41 | 'jcr:primaryType' : "nt:file", 42 | "jcr:content" : "type:Binary, value:/files/air_jordan.jpg" 43 | } 44 | }, 45 | 345678 : { 46 | id : '345678', 47 | name : "air_jordan.jpg", 48 | mimeType : "jpg", 49 | contentType : "photography", 50 | resolution : '300ppi', 51 | binary : { 52 | 'jcr:primaryType' : "nt:file", 53 | "jcr:content" : "type:Binary, value:/files/air_jordan.jpg" 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/testing/NodeFactory.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing; 2 | 3 | import javax.jcr.Node; 4 | import javax.jcr.Property; 5 | import javax.jcr.RepositoryException; 6 | import javax.jcr.Value; 7 | import javax.jcr.nodetype.NodeType; 8 | import java.util.List; 9 | 10 | /** 11 | * Common interface for Node Factories 12 | * 13 | * @author Daniel Valencia (daniel@tacitknowledge.com) 14 | */ 15 | public interface NodeFactory { 16 | 17 | String JCR_PRIMARY_TYPE = "jcr:primaryType"; 18 | 19 | Property createProperty(Node parent, String name, String propertyValue, int propertyType) throws RepositoryException; 20 | 21 | Property createMultiValuedProperty(Node parent, String name, String[] propertyValues) throws RepositoryException; 22 | 23 | Node createNode(Node parentNode, String nodeName, String nodeTypeName) throws RepositoryException; 24 | 25 | /** 26 | * Creates a mock node as a child of the given parent 27 | * @param parent Parent for the new node 28 | * @param name Node name 29 | * @return Node 30 | * @throws RepositoryException If a repository error happens 31 | */ 32 | Node createNode(Node parent, String name) throws RepositoryException; 33 | 34 | /** 35 | * Creates a mock node 36 | * @param name Node name 37 | * @return Node 38 | * @throws RepositoryException If a repository error happens 39 | */ 40 | Node createNode(String name) throws RepositoryException; 41 | 42 | /** 43 | * Creates a node iterator for the given child nodes in relation with their parent. 44 | * The parent node must not be null 45 | * @param parent Parent node for the children and the iterator. Must not be null. 46 | * @param childNodes Child nodes to iterate through 47 | * @throws RepositoryException If a repository error happens 48 | */ 49 | void createIteratorFor(Node parent, List childNodes) throws RepositoryException; 50 | 51 | void createPropertyIteratorFor(Node parent, final List propertyList) throws RepositoryException; 52 | 53 | Value createValueFor(Property property, String valueStr, int valueType) throws RepositoryException; 54 | 55 | Node createNode(Node parent, String name, NodeType nodeType) throws RepositoryException; 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/testing/utils/JcrTestingUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.utils; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import javax.jcr.Node; 7 | import javax.jcr.Property; 8 | import javax.jcr.RepositoryException; 9 | import javax.jcr.Value; 10 | import java.util.ArrayList; 11 | import java.util.Iterator; 12 | import java.util.List; 13 | 14 | import static org.junit.Assert.assertEquals; 15 | import static org.junit.Assert.fail; 16 | import static org.mockito.Mockito.mock; 17 | import static org.mockito.Mockito.when; 18 | 19 | public class JcrTestingUtilsTest { 20 | 21 | private Property property; 22 | private List list; 23 | private Node node; 24 | private Iterator iterator; 25 | 26 | @Before 27 | public void setUp() throws Exception { 28 | property = mock(Property.class); 29 | when(property.getType()).thenReturn(1); 30 | Value value = mock(Value.class); 31 | when(value.getString()).thenReturn("value"); 32 | when(property.getValue()).thenReturn(value); 33 | list = new ArrayList(); 34 | node = mock(Node.class); 35 | 36 | list.add(node); 37 | list.add(node); 38 | list.add(node); 39 | list.add(node); 40 | list.add(node); 41 | 42 | iterator = list.iterator(); 43 | } 44 | 45 | @Test 46 | public void shouldAssertIteratorCountCorrectly() { 47 | JcrTestingUtils.assertIteratorCount(iterator, 5); 48 | } 49 | 50 | @Test 51 | public void shouldThrowAssertionErrorIfCountIsIncorrect() { 52 | 53 | try { 54 | JcrTestingUtils.assertIteratorCount(iterator, 6); 55 | fail("Should have thrown AssertionError since count is not right."); 56 | } catch (AssertionError error) { 57 | assertEquals("Expected 1 node expected:<6> but was:<5>", error.getMessage()); 58 | } 59 | } 60 | 61 | @Test 62 | public void shouldAssertPropertyTypeIsExpected() throws RepositoryException { 63 | JcrTestingUtils.assertPropertyType(property, 1); 64 | } 65 | 66 | @Test 67 | public void shouldAssertPropertyIsExpected() throws RepositoryException { 68 | JcrTestingUtils.assertProperty(property, 1, "value"); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/testing/utils/PropertyTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.utils; 2 | 3 | import javax.jcr.PropertyType; 4 | import javax.jcr.RepositoryException; 5 | import javax.jcr.Value; 6 | 7 | /** 8 | * @author Daniel Valencia (daniel@tacitknowledge.com) 9 | */ 10 | public enum PropertyTypeEnum { 11 | BINARY(PropertyType.BINARY){ 12 | @Override 13 | public Object getObjectValue(Value value) throws RepositoryException { 14 | return value.getBinary(); 15 | } 16 | }, 17 | BOOLEAN(PropertyType.BOOLEAN){ 18 | @Override 19 | public Object getObjectValue(Value value) throws RepositoryException { 20 | return value.getBoolean(); 21 | } 22 | }, 23 | DATE(PropertyType.DATE){ 24 | @Override 25 | public Object getObjectValue(Value value) throws RepositoryException { 26 | return value.getDate(); 27 | } 28 | }, 29 | DECIMAL(PropertyType.DECIMAL){ 30 | @Override 31 | public Object getObjectValue(Value value) throws RepositoryException { 32 | return value.getDecimal(); 33 | } 34 | }, 35 | DOUBLE(PropertyType.DOUBLE){ 36 | @Override 37 | public Object getObjectValue(Value value) throws RepositoryException { 38 | return value.getDouble(); 39 | } 40 | }, 41 | LONG(PropertyType.LONG){ 42 | @Override 43 | public Object getObjectValue(Value value) throws RepositoryException { 44 | return value.getLong(); 45 | } 46 | }, 47 | REFERENCE(PropertyType.REFERENCE), 48 | STRING(PropertyType.STRING); 49 | 50 | private int propertyType; 51 | 52 | PropertyTypeEnum(int propertyType) { 53 | this.propertyType = propertyType; 54 | } 55 | 56 | public int getPropertyType(){ 57 | return propertyType; 58 | } 59 | 60 | public Object getObjectValue(Value value) throws RepositoryException { 61 | return value.getString(); 62 | } 63 | 64 | public static PropertyTypeEnum fromType(int type){ 65 | PropertyTypeEnum propertyTypeEnum = null; 66 | 67 | for(PropertyTypeEnum enumVal: values()){ 68 | if(type == enumVal.getPropertyType()){ 69 | propertyTypeEnum = enumVal; 70 | } 71 | } 72 | 73 | if(propertyTypeEnum == null) throw new RuntimeException("There's no PropertyTypeEnum for type: " + type); 74 | 75 | return propertyTypeEnum; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/mocking/domain/PropertyDefinitionMap.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.mocking.domain; 2 | 3 | import java.util.HashMap; 4 | import java.util.regex.Matcher; 5 | import java.util.regex.Pattern; 6 | 7 | import javax.jcr.PropertyType; 8 | 9 | import org.apache.commons.lang3.StringUtils; 10 | 11 | /** 12 | * @author Daniel Valencia (daniel@tacitknowledge.com) 13 | */ 14 | public class PropertyDefinitionMap extends HashMap 15 | { 16 | 17 | public static final String VALUE = "value"; 18 | public static final String TYPE = "type"; 19 | public static final String KEY_VALUE_SEPARATOR = ":"; 20 | public static final String PAIR_SEPARATOR = ","; 21 | 22 | public PropertyDefinitionMap(String propertyDefinition) 23 | { 24 | if(propertyDefinition == null) 25 | { 26 | throw new RuntimeException("Property definition must not be null"); 27 | } 28 | //"type:Binary,value:/files/air_jordan.jpg" 29 | //'type:String, value:The value of the property' 30 | //"type:Binary,value:/files/air_jordan.jpg ,required:true"; 31 | Pattern pattern = Pattern.compile("type:([a-zA-Z]+),\\s*value:(.+)"); 32 | Matcher matcher = pattern.matcher(propertyDefinition); 33 | if(matcher.find()) 34 | { 35 | String key = matcher.group(1); 36 | put(TYPE, key); 37 | String value = matcher.group(2); 38 | put(VALUE, value); 39 | } 40 | else if(propertyDefinition.contains(KEY_VALUE_SEPARATOR)) 41 | { 42 | String key = extractKeyFromDefinition(propertyDefinition); 43 | if(key.equals(TYPE) || key.equals(VALUE)) 44 | { 45 | insertEntry(propertyDefinition); 46 | } 47 | } 48 | 49 | // If property definition doesn't contain any tokens then the definition corresponds to the value. 50 | if(size() == 0) 51 | { 52 | put(VALUE, propertyDefinition); 53 | } 54 | } 55 | 56 | public String getValue() 57 | { 58 | String value = get(VALUE); 59 | if(value == null) value = StringUtils.EMPTY; 60 | return value; 61 | } 62 | 63 | public int getType() 64 | { 65 | int intType = PropertyType.STRING; 66 | String type = get(TYPE); 67 | if(type != null) 68 | { 69 | intType = PropertyType.valueFromName(type); 70 | } 71 | return intType; 72 | } 73 | 74 | private void insertEntry(String propertyDefinition) 75 | { 76 | String key = extractKeyFromDefinition(propertyDefinition); 77 | String value = extractValueFromDefinition(propertyDefinition); 78 | put(key, value); 79 | } 80 | 81 | private String extractValueFromDefinition(String token) 82 | { 83 | return token.substring(token.indexOf(KEY_VALUE_SEPARATOR) + 1, token.length()).trim(); 84 | } 85 | 86 | private String extractKeyFromDefinition(String token) 87 | { 88 | return token.substring(0, token.indexOf(KEY_VALUE_SEPARATOR)).trim(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/mocking/domain/PropertyDefinitionMapTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.mocking.domain; 2 | 3 | import org.junit.Test; 4 | 5 | import javax.jcr.PropertyType; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.junit.Assert.fail; 9 | 10 | /** 11 | * @author Daniel Valencia (daniel@tacitknowledge.com) 12 | */ 13 | public class PropertyDefinitionMapTest { 14 | 15 | @Test 16 | public void shouldReturnCorrectPropertyType() { 17 | String valueString = "type:Binary, value:/files/air_jordan.jpg"; 18 | PropertyDefinitionMap propertyDefinitionMap = new PropertyDefinitionMap(valueString); 19 | 20 | int propertyType = propertyDefinitionMap.getType(); 21 | 22 | assertEquals("Expecting Binary Type", PropertyType.BINARY, propertyType); 23 | } 24 | 25 | @Test(expected = IllegalArgumentException.class) 26 | public void shouldThrowExceptionForUnsupportedPropertyTypes() { 27 | String valueString = "type:File"; 28 | 29 | PropertyDefinitionMap propertyDefinitionMap = new PropertyDefinitionMap(valueString); 30 | 31 | propertyDefinitionMap.getType(); 32 | 33 | fail("An IllegalArgumentException exception was expected"); 34 | } 35 | 36 | @Test 37 | public void shouldReturnCorrectPropertyValue() throws Exception { 38 | String valueString = "type:Binary,value:/files/air_jordan.jpg"; 39 | PropertyDefinitionMap propertyDefinitionMap = new PropertyDefinitionMap(valueString); 40 | 41 | String propertyValue = propertyDefinitionMap.getValue(); 42 | 43 | assertEquals("Expecting File Path", "/files/air_jordan.jpg", propertyValue); 44 | 45 | // Now let's test a different scenario in which we have a new attribute 46 | valueString = "type:Binary,value:/files/air_jordan.jpg ,required:true"; 47 | propertyDefinitionMap = new PropertyDefinitionMap(valueString ); 48 | propertyValue = propertyDefinitionMap.getValue(); 49 | 50 | assertEquals("Expected type to be Binary", PropertyType.BINARY, propertyDefinitionMap.getType()); 51 | 52 | assertEquals("Expecting File Path", "/files/air_jordan.jpg ,required:true", propertyValue); 53 | 54 | //issue #23 test commas in a property value 55 | valueString = "Here's a test with a comma,"; 56 | propertyDefinitionMap = new PropertyDefinitionMap(valueString); 57 | propertyValue = propertyDefinitionMap.getValue(); 58 | 59 | assertEquals("Expected type to be Binary", PropertyType.STRING, propertyDefinitionMap.getType()); 60 | 61 | assertEquals("Expecting File Path", valueString, propertyValue); 62 | 63 | } 64 | 65 | @Test 66 | public void shouldSupportPropertyDefinitionsWithColonInItsName() throws Exception 67 | { 68 | String propertyDefinition = "nt:file"; 69 | 70 | PropertyDefinitionMap propertyDefinitionMap = new PropertyDefinitionMap(propertyDefinition); 71 | String propertyValue = propertyDefinitionMap.getValue(); 72 | 73 | assertEquals("Expected value to be nt:file", "nt:file", propertyValue); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/testing/utils/PropertyTypeEnumTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.utils; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import javax.jcr.Binary; 7 | import javax.jcr.PropertyType; 8 | import javax.jcr.RepositoryException; 9 | import javax.jcr.Value; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.math.BigDecimal; 12 | import java.util.Calendar; 13 | 14 | import static org.junit.Assert.assertEquals; 15 | import static org.mockito.Mockito.mock; 16 | import static org.mockito.Mockito.when; 17 | 18 | /** 19 | * @author Daniel Valencia (daniel@tacitknowledge.com) 20 | */ 21 | public class PropertyTypeEnumTest { 22 | 23 | private PropertyTypeEnum stringType; 24 | private PropertyTypeEnum binaryType; 25 | private PropertyTypeEnum longType; 26 | private PropertyTypeEnum dateType; 27 | private PropertyTypeEnum decimalType; 28 | private PropertyTypeEnum doubleType; 29 | private PropertyTypeEnum referenceType; 30 | private PropertyTypeEnum booleanType; 31 | 32 | @Before 33 | public void beforeEachTest(){ 34 | stringType = PropertyTypeEnum.fromType(PropertyType.STRING); 35 | binaryType = PropertyTypeEnum.fromType(PropertyType.BINARY); 36 | booleanType = PropertyTypeEnum.fromType(PropertyType.BOOLEAN); 37 | longType = PropertyTypeEnum.fromType(PropertyType.LONG); 38 | dateType = PropertyTypeEnum.fromType(PropertyType.DATE); 39 | decimalType = PropertyTypeEnum.fromType(PropertyType.DECIMAL); 40 | doubleType = PropertyTypeEnum.fromType(PropertyType.DOUBLE); 41 | referenceType = PropertyTypeEnum.fromType(PropertyType.REFERENCE); 42 | } 43 | 44 | @Test 45 | public void shouldGetCorrectObjectValueAndType() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, RepositoryException { 46 | Value value = mock(Value.class); 47 | Binary mockedBinary = mock(Binary.class); 48 | String mockedString = "It freaking works!!!"; 49 | Long mockedLong = 123L; 50 | String reference = "/reference/String"; 51 | Double mockedDouble = 3.0; 52 | BigDecimal mockedBigDecimal = new BigDecimal(2.0); 53 | boolean mockedBoolean = true; 54 | Calendar mockedCalendar = Calendar.getInstance(); 55 | 56 | 57 | when(value.getBinary()).thenReturn(mockedBinary); 58 | when(value.getString()).thenReturn(mockedString); 59 | when(value.getLong()).thenReturn(mockedLong); 60 | when(value.getDecimal()).thenReturn(mockedBigDecimal); 61 | when(value.getBoolean()).thenReturn(mockedBoolean); 62 | when(value.getDouble()).thenReturn(mockedDouble); 63 | when(value.getDate()).thenReturn(mockedCalendar); 64 | 65 | assertEquals(mockedString, stringType.getObjectValue(value)); 66 | assertEquals(mockedBoolean, booleanType.getObjectValue(value)); 67 | assertEquals(mockedBinary, binaryType.getObjectValue(value)); 68 | assertEquals(mockedLong, longType.getObjectValue(value)); 69 | assertEquals(mockedCalendar, dateType.getObjectValue(value)); 70 | assertEquals(mockedBigDecimal, decimalType.getObjectValue(value)); 71 | assertEquals(mockedDouble, doubleType.getObjectValue(value)); 72 | 73 | when(value.getString()).thenReturn(reference); 74 | assertEquals(reference, referenceType.getObjectValue(value)); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/testing/utils/JcrMockingUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.utils; 2 | 3 | import org.junit.BeforeClass; 4 | import org.junit.Test; 5 | 6 | import javax.jcr.Binary; 7 | import javax.jcr.Node; 8 | import javax.jcr.Property; 9 | import javax.jcr.RepositoryException; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | 13 | import static org.junit.Assert.assertEquals; 14 | import static org.junit.Assert.assertNotNull; 15 | 16 | /** 17 | * @author Daniel Valencia (daniel@tacitknowledge.com) 18 | */ 19 | public class JcrMockingUtilsTest { 20 | 21 | private InputStream assetsJsonFile; 22 | 23 | private String jsonNodeHierarchy = 24 | "{" + 25 | " parentNode: {" + 26 | " childNode: {" + 27 | " myFile: {" + 28 | " 'jcr:primaryType' : 'nt:file', " + 29 | " 'jcr:content' : {" + 30 | " 'jcr:data' : 'type:Binary, value:/files/air_jordan.jpg'" + 31 | " }" + 32 | " }" + 33 | " }" + 34 | " }" + 35 | "}"; 36 | 37 | 38 | @BeforeClass 39 | public static void setup() throws Exception { 40 | } 41 | 42 | @Test 43 | public void shouldCreateNodesFromString() throws Exception { 44 | Node rootNode = JcrMockingUtils.createNodesFromJsonString(jsonNodeHierarchy); 45 | assertNodeHierarchy(rootNode); 46 | } 47 | 48 | @Test 49 | public void shouldCreateNodesFromStringWithoutNodeTypeManager() throws Exception { 50 | Node rootNode = JcrMockingUtils.createNodesFromJsonString(jsonNodeHierarchy); 51 | assertNodeHierarchy(rootNode); 52 | } 53 | 54 | @Test 55 | public void shouldCreateNodeStructureFromJsonFile() throws RepositoryException, IOException { 56 | assetsJsonFile = getClass().getResourceAsStream("/assets.json"); 57 | Node rootNode = JcrMockingUtils.createNodesFromJsonFile(assetsJsonFile); 58 | assertFileNodeHierarchy(rootNode); 59 | } 60 | 61 | @Test 62 | public void shouldCreateNodeStructureFromJsonFileWithoutNodeTypeManager() throws RepositoryException, IOException { 63 | assetsJsonFile = getClass().getResourceAsStream("/assets.json"); 64 | Node rootNode = JcrMockingUtils.createNodesFromJsonFile(assetsJsonFile); 65 | assertFileNodeHierarchy(rootNode); 66 | } 67 | 68 | 69 | private void assertFileNodeHierarchy(Node rootNode) throws RepositoryException { 70 | assertNotNull(rootNode); 71 | 72 | Node assetsNode = rootNode.getNode("digitalAsset"); 73 | assertEquals("Expected digitalAsset node", "digitalAsset", assetsNode.getName()); 74 | 75 | Property mimeType = assetsNode.getProperty("mimeType"); 76 | assertEquals("Expected jpg", "jpg", mimeType.getString()); 77 | 78 | Node binaryNode = assetsNode.getNode("binary"); 79 | assertNotNull("Expected a non null binary", binaryNode.getProperty("jcr:content").getBinary()); 80 | } 81 | 82 | private void assertNodeHierarchy(Node rootNode) throws RepositoryException { 83 | Node parentNode = rootNode.getNode("parentNode"); 84 | 85 | assertNotNull("Expected parentNode not to be null", parentNode); 86 | 87 | Node fileNode = parentNode.getNode("childNode/myFile"); 88 | assertEquals("Expected nt:file", "nt:file", fileNode.getPrimaryNodeType().getName()); 89 | 90 | Binary binary = fileNode.getNode("jcr:content").getProperty("jcr:data").getBinary(); 91 | assertNotNull("Expected binary not to be null", binary); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/mocking/impl/JsonMockingServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.mocking.impl; 2 | 3 | 4 | import com.tacitknowledge.jcr.testing.NodeFactory; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.mockito.ArgumentCaptor; 9 | 10 | import javax.jcr.Node; 11 | import javax.jcr.PropertyType; 12 | import javax.jcr.RepositoryException; 13 | import java.util.List; 14 | 15 | import static junit.framework.Assert.*; 16 | import static org.mockito.Mockito.*; 17 | 18 | public class JsonMockingServiceTest { 19 | 20 | private Node parentNode; 21 | private NodeFactory nodeFactory; 22 | private JsonMockService mockService; 23 | 24 | @Before 25 | public void setUp() throws Exception { 26 | parentNode = mock(Node.class); 27 | nodeFactory = mock(NodeFactory.class); 28 | mockService = new JsonMockService(nodeFactory); 29 | } 30 | 31 | @Test 32 | public void shouldCreateNodesFromJsonString() throws RepositoryException { 33 | when(nodeFactory.createNode(StringUtils.EMPTY)).thenReturn(parentNode); 34 | 35 | Node actual = mockService.fromString("{\"childElementName\":\"propertyValue\"}"); 36 | 37 | assertEquals(parentNode, actual); 38 | verify(nodeFactory).createProperty(parentNode, "childElementName", "propertyValue", PropertyType.STRING); 39 | ArgumentCaptor listCaptor = ArgumentCaptor.forClass(List.class); 40 | verify(nodeFactory).createIteratorFor(eq(parentNode), listCaptor.capture()); 41 | List actualList = listCaptor.getValue(); 42 | assertTrue(actualList.isEmpty()); 43 | 44 | } 45 | 46 | @Test 47 | public void shouldCreateNodesFromJsonStringWithParent() throws RepositoryException { 48 | Node actual = mockService.fromString(parentNode, "{\"childElementName\":\"propertyValue\"}"); 49 | 50 | assertEquals(parentNode, actual); 51 | verify(nodeFactory).createProperty(parentNode, "childElementName", "propertyValue", PropertyType.STRING); 52 | ArgumentCaptor listCaptor = ArgumentCaptor.forClass(List.class); 53 | verify(nodeFactory).createIteratorFor(eq(parentNode), listCaptor.capture()); 54 | List actualList = listCaptor.getValue(); 55 | assertTrue(actualList.isEmpty()); 56 | } 57 | 58 | 59 | @Test 60 | public void shouldCreateTreeNodeFromJson() throws RepositoryException { 61 | Node childNode = mock(Node.class); 62 | when(nodeFactory.createNode(parentNode, "parentElementName")).thenReturn(childNode); 63 | Node actual = mockService.fromString(parentNode, "{\"parentElementName\":{\"childElementName\":\"propertyValue\"}}"); 64 | 65 | assertEquals(parentNode, actual); 66 | 67 | verify(nodeFactory).createProperty(childNode, "childElementName", "propertyValue", PropertyType.STRING); 68 | ArgumentCaptor listCaptor = ArgumentCaptor.forClass(List.class); 69 | verify(nodeFactory).createIteratorFor(eq(parentNode), listCaptor.capture()); 70 | List actualList = listCaptor.getValue(); 71 | 72 | assertFalse(actualList.isEmpty()); 73 | } 74 | 75 | @Test 76 | public void shouldCreateTreeNodeFromJsonUsingNodeType() throws RepositoryException { 77 | Node childNode = mock(Node.class); 78 | when(nodeFactory.createNode(parentNode, "parentElement", "propertyValue")).thenReturn(childNode); 79 | Node actual = mockService.fromString(parentNode, "{\"parentElement\":{\"nodeType\":\"propertyValue\"}}"); 80 | 81 | assertEquals(parentNode, actual); 82 | 83 | verify(nodeFactory, never()).createProperty(childNode, "childElementName", "propertyValue", PropertyType.STRING); 84 | ArgumentCaptor listCaptor = ArgumentCaptor.forClass(List.class); 85 | verify(nodeFactory).createIteratorFor(eq(parentNode), listCaptor.capture()); 86 | List actualList = listCaptor.getValue(); 87 | 88 | assertFalse(actualList.isEmpty()); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/testing/impl/NodeIteratorAdapterTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.impl; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import javax.jcr.Node; 7 | import java.util.ArrayList; 8 | import java.util.Iterator; 9 | import java.util.List; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | import static org.junit.Assert.assertTrue; 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.when; 15 | 16 | public class NodeIteratorAdapterTest { 17 | 18 | private Iterator iterator; 19 | private NodeIteratorAdapter nodeIteratorAdapter; 20 | private Node node; 21 | private List list; 22 | private Node secondNode; 23 | private Node thirdNode; 24 | private Node fourthNode; 25 | private Node fifthNode; 26 | 27 | @Before 28 | public void setUp() throws Exception { 29 | iterator = mock(Iterator.class); 30 | node = mock(Node.class); 31 | 32 | when(iterator.next()).thenReturn(node); 33 | when(iterator.hasNext()).thenReturn(true).thenReturn(false); 34 | 35 | nodeIteratorAdapter = new NodeIteratorAdapter(iterator); 36 | list = new ArrayList(); 37 | secondNode = mock(Node.class); 38 | thirdNode = mock(Node.class); 39 | fourthNode = mock(Node.class); 40 | fifthNode = mock(Node.class); 41 | 42 | when(node.toString()).thenReturn("1"); 43 | when(secondNode.toString()).thenReturn("2"); 44 | when(thirdNode.toString()).thenReturn("3"); 45 | when(fourthNode.toString()).thenReturn("4"); 46 | 47 | list.add(node); 48 | list.add(secondNode); 49 | list.add(thirdNode); 50 | list.add(fourthNode); 51 | list.add(fifthNode); 52 | 53 | } 54 | 55 | @Test 56 | public void shouldRetrieveNextNodes() { 57 | 58 | Node actual = nodeIteratorAdapter.nextNode(); 59 | assertEquals(node, actual); 60 | 61 | } 62 | 63 | @Test 64 | public void shouldRetrieveNextNode() { 65 | when(iterator.hasNext()).thenReturn(true); 66 | boolean hasNext = nodeIteratorAdapter.hasNext(); 67 | assertTrue(hasNext); 68 | } 69 | 70 | @Test 71 | public void shouldRetrieveNextObject() { 72 | 73 | Node actual = (Node) nodeIteratorAdapter.next(); 74 | 75 | assertEquals(node, actual); 76 | 77 | } 78 | 79 | @Test 80 | public void shouldCallIteratorRemover() { 81 | nodeIteratorAdapter.remove(); 82 | assertEquals(0, nodeIteratorAdapter.getSize()); 83 | } 84 | 85 | @Test 86 | public void shouldSkipProperly() { 87 | 88 | nodeIteratorAdapter = new NodeIteratorAdapter(list.iterator()); 89 | 90 | nodeIteratorAdapter.skip(1); 91 | assertEquals(secondNode, nodeIteratorAdapter.nextNode()); 92 | 93 | nodeIteratorAdapter.skip(1); 94 | assertEquals(fourthNode, nodeIteratorAdapter.nextNode()); 95 | 96 | assertEquals(fifthNode, nodeIteratorAdapter.nextNode()); 97 | 98 | } 99 | 100 | @Test 101 | public void shouldShowCurrentPosition() { 102 | nodeIteratorAdapter = new NodeIteratorAdapter(list.iterator()); 103 | 104 | assertEquals(0, nodeIteratorAdapter.getPosition()); 105 | 106 | nodeIteratorAdapter.skip(2); 107 | 108 | assertEquals(2, nodeIteratorAdapter.getPosition()); 109 | 110 | nodeIteratorAdapter.next(); 111 | 112 | assertEquals(3, nodeIteratorAdapter.getPosition()); 113 | 114 | nodeIteratorAdapter.nextNode(); 115 | 116 | assertEquals(4, nodeIteratorAdapter.getPosition()); 117 | 118 | nodeIteratorAdapter.remove(); 119 | 120 | assertEquals(5, nodeIteratorAdapter.getPosition()); 121 | 122 | } 123 | 124 | @Test 125 | public void shouldRetrieveCorrectSize() { 126 | nodeIteratorAdapter = new NodeIteratorAdapter(list.iterator()); 127 | 128 | assertEquals(5, nodeIteratorAdapter.getSize()); 129 | 130 | nodeIteratorAdapter.skip(2); 131 | 132 | assertEquals(3, nodeIteratorAdapter.getSize()); 133 | 134 | nodeIteratorAdapter.next(); 135 | 136 | assertEquals(2, nodeIteratorAdapter.getSize()); 137 | 138 | nodeIteratorAdapter.nextNode(); 139 | 140 | assertEquals(1, nodeIteratorAdapter.getSize()); 141 | 142 | nodeIteratorAdapter.remove(); 143 | 144 | assertEquals(0, nodeIteratorAdapter.getSize()); 145 | 146 | } 147 | 148 | 149 | } 150 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/testing/impl/PropertyIteratorAdapterTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.impl; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import javax.jcr.Property; 7 | import java.util.ArrayList; 8 | import java.util.Iterator; 9 | import java.util.List; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | import static org.junit.Assert.assertTrue; 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.when; 15 | 16 | public class PropertyIteratorAdapterTest { 17 | 18 | private Iterator iterator; 19 | private PropertyIteratorAdapter propertyIteratorAdapter; 20 | private Property property; 21 | private List list; 22 | private Property secondProperty; 23 | private Property thirdProperty; 24 | private Property fourthProperty; 25 | private Property fifthProperty; 26 | 27 | @Before 28 | public void setUp() throws Exception { 29 | iterator = mock(Iterator.class); 30 | property = mock(Property.class); 31 | 32 | when(iterator.next()).thenReturn(property); 33 | when(iterator.hasNext()).thenReturn(true).thenReturn(false); 34 | 35 | propertyIteratorAdapter = new PropertyIteratorAdapter(iterator); 36 | list = new ArrayList(); 37 | secondProperty = mock(Property.class); 38 | thirdProperty = mock(Property.class); 39 | fourthProperty = mock(Property.class); 40 | fifthProperty = mock(Property.class); 41 | 42 | when(property.toString()).thenReturn("1"); 43 | when(secondProperty.toString()).thenReturn("2"); 44 | when(thirdProperty.toString()).thenReturn("3"); 45 | when(fourthProperty.toString()).thenReturn("4"); 46 | 47 | list.add(property); 48 | list.add(secondProperty); 49 | list.add(thirdProperty); 50 | list.add(fourthProperty); 51 | list.add(fifthProperty); 52 | 53 | } 54 | 55 | @Test 56 | public void shouldRetrieveNextProperty() { 57 | Property actual = propertyIteratorAdapter.nextProperty(); 58 | assertEquals(property, actual); 59 | 60 | } 61 | 62 | @Test 63 | public void shouldRetrieveHaveNextProperty() { 64 | when(iterator.hasNext()).thenReturn(true); 65 | boolean hasNext = propertyIteratorAdapter.hasNext(); 66 | assertTrue(hasNext); 67 | } 68 | 69 | @Test 70 | public void shouldRetrieveNext() { 71 | 72 | Property actual = propertyIteratorAdapter.next(); 73 | 74 | assertEquals(property, actual); 75 | 76 | } 77 | 78 | @Test 79 | public void shouldCallIteratorRemover() { 80 | propertyIteratorAdapter.remove(); 81 | assertEquals(0, propertyIteratorAdapter.getSize()); 82 | } 83 | 84 | @Test 85 | public void shouldSkipProperly() { 86 | 87 | propertyIteratorAdapter = new PropertyIteratorAdapter(list.iterator()); 88 | 89 | propertyIteratorAdapter.skip(1); 90 | assertEquals(secondProperty, propertyIteratorAdapter.nextProperty()); 91 | 92 | propertyIteratorAdapter.skip(1); 93 | assertEquals(fourthProperty, propertyIteratorAdapter.nextProperty()); 94 | 95 | assertEquals(fifthProperty, propertyIteratorAdapter.nextProperty()); 96 | 97 | } 98 | 99 | @Test 100 | public void shouldShowCurrentPosition() { 101 | propertyIteratorAdapter = new PropertyIteratorAdapter(list.iterator()); 102 | 103 | assertEquals(0, propertyIteratorAdapter.getPosition()); 104 | 105 | propertyIteratorAdapter.skip(2); 106 | 107 | assertEquals(2, propertyIteratorAdapter.getPosition()); 108 | 109 | propertyIteratorAdapter.next(); 110 | 111 | assertEquals(3, propertyIteratorAdapter.getPosition()); 112 | 113 | propertyIteratorAdapter.nextProperty(); 114 | 115 | assertEquals(4, propertyIteratorAdapter.getPosition()); 116 | 117 | propertyIteratorAdapter.remove(); 118 | 119 | assertEquals(5, propertyIteratorAdapter.getPosition()); 120 | 121 | } 122 | 123 | @Test 124 | public void shouldRetrieveCorrectSize() { 125 | propertyIteratorAdapter = new PropertyIteratorAdapter(list.iterator()); 126 | 127 | assertEquals(5, propertyIteratorAdapter.getSize()); 128 | 129 | propertyIteratorAdapter.skip(2); 130 | 131 | assertEquals(3, propertyIteratorAdapter.getSize()); 132 | 133 | propertyIteratorAdapter.next(); 134 | 135 | assertEquals(2, propertyIteratorAdapter.getSize()); 136 | 137 | propertyIteratorAdapter.nextProperty(); 138 | 139 | assertEquals(1, propertyIteratorAdapter.getSize()); 140 | 141 | propertyIteratorAdapter.remove(); 142 | 143 | assertEquals(0, propertyIteratorAdapter.getSize()); 144 | 145 | } 146 | 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/mocking/impl/JsonMockService.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.mocking.impl; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonObject; 6 | import com.tacitknowledge.jcr.mocking.JcrMockService; 7 | import com.tacitknowledge.jcr.mocking.domain.PropertyDefinitionMap; 8 | import com.tacitknowledge.jcr.testing.NodeFactory; 9 | import org.apache.commons.lang3.StringUtils; 10 | 11 | import javax.jcr.Node; 12 | import javax.jcr.Property; 13 | import javax.jcr.RepositoryException; 14 | import java.util.*; 15 | 16 | /** 17 | * @author Daniel Valencia (daniel@tacitknowledge.com) 18 | */ 19 | public class JsonMockService implements JcrMockService { 20 | 21 | private final NodeFactory nodeFactory; 22 | 23 | public JsonMockService(NodeFactory nodeFactory){ 24 | this.nodeFactory = nodeFactory; 25 | } 26 | 27 | @Override 28 | public Node fromString(Node parentNode, String jsonNodeStructure) throws RepositoryException { 29 | JsonObject object = parseJson(jsonNodeStructure); 30 | return buildChildNodes(object, parentNode); 31 | } 32 | 33 | @Override 34 | public Node fromString(String jsonNodeStructure) throws RepositoryException { 35 | JsonObject jsonNodeObject = parseJson(jsonNodeStructure); 36 | return buildChildNodes(jsonNodeObject, null); 37 | } 38 | 39 | /** 40 | * Builds nodes from the given JSON object as children of the given parent 41 | * @param parentJsonObject JsonObject to create the children from 42 | * @param parent Parent node 43 | * @return Parent node 44 | * @throws RepositoryException If a repository error happens 45 | */ 46 | private Node buildChildNodes(JsonObject parentJsonObject, Node parent) throws RepositoryException { 47 | Node childNode; 48 | List childNodes = new ArrayList(); 49 | List properties = new ArrayList(); 50 | if(parent == null){ 51 | parent = nodeFactory.createNode(StringUtils.EMPTY); 52 | } 53 | Set> childElements = parentJsonObject.entrySet(); 54 | 55 | for(Map.Entry childEntry: childElements){ 56 | String childElementName = childEntry.getKey(); 57 | JsonElement childElement = childEntry.getValue(); 58 | if(childElement.isJsonObject()){ 59 | JsonObject childJsonObject = childElement.getAsJsonObject(); 60 | JsonElement nodeTypeElement = childJsonObject.get(NodeFactory.JCR_PRIMARY_TYPE); 61 | if(nodeTypeElement != null ){ 62 | String nodeType = nodeTypeElement.getAsString(); 63 | childNode = nodeFactory.createNode(parent, childElementName, nodeType); 64 | }else{ 65 | childNode = nodeFactory.createNode(parent, childElementName); 66 | } 67 | childNodes.add(childNode); 68 | buildChildNodes(childJsonObject, childNode); 69 | }else if(childElement.isJsonPrimitive()){ 70 | String childElementValue = childElement.getAsString(); 71 | PropertyDefinitionMap propertyDefinitionMap = new PropertyDefinitionMap(childElementValue); 72 | int propertyType = propertyDefinitionMap.getType(); 73 | String propertyValue = propertyDefinitionMap.getValue(); 74 | Property property = nodeFactory.createProperty(parent, childElementName, propertyValue, propertyType); 75 | properties.add(property); 76 | }else if(childElement.isJsonArray()){ 77 | String[] values = readMultiValuedProperty(childElement); 78 | Property property = nodeFactory.createMultiValuedProperty(parent, childElementName, values); 79 | properties.add(property); 80 | } 81 | } 82 | nodeFactory.createIteratorFor(parent, childNodes); 83 | nodeFactory.createPropertyIteratorFor(parent, properties); 84 | return parent; 85 | } 86 | 87 | private String[] readMultiValuedProperty(JsonElement propertyElement) { 88 | List childElementValues = new ArrayList(); 89 | JsonArray jsonArray = propertyElement.getAsJsonArray(); 90 | Iterator arrayIterator = jsonArray.iterator(); 91 | while(arrayIterator.hasNext()) { 92 | JsonElement element = arrayIterator.next(); 93 | if(!element.isJsonPrimitive()) { 94 | return new String[] {}; 95 | } 96 | childElementValues.add(element.getAsString()); 97 | } 98 | return childElementValues.toArray(new String[childElementValues.size()]); 99 | } 100 | 101 | /** 102 | * Parses a given String as JSON 103 | * @param jsonString - JSON object as String 104 | * @return JsonObject 105 | */ 106 | private JsonObject parseJson(String jsonString) { 107 | com.google.gson.JsonParser parser = new com.google.gson.JsonParser(); 108 | return parser.parse(jsonString).getAsJsonObject(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.tacitknowledge 5 | jcr-mock 6 | 2.1.6-SNAPSHOT 7 | jar 8 | JCR Mock 9 | Testing and mocking utilities for the JCR 10 | https://github.com/tacitknowledge/jcr-mock 11 | 12 | 13 | The Apache Software License, Version 2.0 14 | http://www.apache.org/licenses/LICENSE-2.0.txt 15 | repo 16 | 17 | 18 | 19 | 20 | com.tacitknowledge 21 | oss-parent 22 | 2 23 | 24 | 25 | 26 | scm:git:https://github.com/tacitknowledge/jcr-mock.git 27 | scm:git:git@github.com:tacitknowledge/jcr-mock.git 28 | https://github.com/tacitknowledge/jcr-mock 29 | 30 | 31 | 32 | 33 | dvalencia 34 | Daniel Valencia 35 | daniel@tacitknowledge.com 36 | 37 | 38 | saskew 39 | Scott Askew 40 | scott@tacitknowledge.com 41 | 42 | 43 | ulisespulido 44 | Ulises Pulido 45 | upulido@tacitknowledge.com 46 | 47 | 48 | alayouni 49 | Ahmed Layouni 50 | alayouni@tacitknowledge.com 51 | 52 | 53 | 54 | 55 | 56 | javax.jcr 57 | jcr 58 | 2.0 59 | 60 | 61 | org.slf4j 62 | slf4j-log4j12 63 | 1.6.0 64 | 65 | 66 | org.mockito 67 | mockito-core 68 | 1.9.0 69 | 70 | 71 | org.apache.commons 72 | commons-lang3 73 | 3.1 74 | 75 | 76 | commons-collections 77 | commons-collections 78 | 3.2.2 79 | 80 | 81 | commons-io 82 | commons-io 83 | 2.7 84 | 85 | 86 | junit 87 | junit 88 | 4.13.1 89 | compile 90 | 91 | 92 | com.google.code.gson 93 | gson 94 | 2.1 95 | 96 | 97 | 98 | 99 | 100 | 101 | org.codehaus.mojo 102 | cobertura-maven-plugin 103 | 2.5.1 104 | 105 | 106 | ${coverage.branchRate} 107 | ${coverage.lineRate} 108 | ${coverage.haltOnFailure} 109 | ${coverage.totalBranchRate} 110 | ${coverage.totalLineRate} 111 | ${coverage.packageLineRate} 112 | ${coverage.packageBranchRate} 113 | 114 | xml 115 | html 116 | 117 | 118 | 119 | 120 | check 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /checkstyle.config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 55 | 56 | 57 | 58 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JCR Mock [![Build Status](https://travis-ci.org/tacitknowledge/jcr-mock.png?branch=master)](https://travis-ci.org/tacitknowledge/jcr-mock) 2 | ======== 3 | 4 | A JCR node mocking library. 5 | 6 | Intent 7 | ------ 8 | 9 | The intent of this framework is to eliminate boilerplate code for setting up JCR node structures in unit tests by 10 | writing them in an easy to read format such as JSON. For example: 11 | 12 | 1. Say you're working on an application which uses a JCR repository for storing product content. 13 | 14 | 2. One feature of this application may be related to building an API to search for products. 15 | 16 | 4. In order to write unit tests for the JCR you'll need to setup some test data. You can do this in 2 ways: 17 | - Use a [TransientRepository](http://jackrabbit.apache.org/api/2.2/org/apache/jackrabbit/core/TransientRepository.html) 18 | and populate it with some data. 19 | - Or you can use a mocking framework (such as mockito) to mock out the repository and the node structure. 20 | 21 | 5. For this example we'll use mockito. 22 | 23 | 6. Let's say that the node structure looks like the following: 24 | ``` 25 | /products 26 | /awesome_shoe 27 | - name 28 | - description 29 | - price 30 | /awesome_shirt 31 | - name 32 | - description 33 | - price 34 | /awesome_jeans 35 | - name 36 | - description 37 | - price 38 | ``` 39 | 40 | 7. In order to mock a structure with 1 products with 1 digital asset in the repository we'd do something like this: 41 | 42 | ```java 43 | Node productBaseNode = mock(Node.class); 44 | Node awesomeShoeNode = mock(Node.class); 45 | Node awesomeShirtNode = mock(Node.class); 46 | Node awesomeJeansNode = mock(Node.class); 47 | 48 | NodeIterator nodeIterator = mock(NodeIterator.class); 49 | when(nodeIterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false); 50 | when(nodeIterator.nextNode()) 51 | .thenReturn(awesomeShoeNode); 52 | .thenReturn(awesomeShirtNode); 53 | .thenReturn(awesomeJeansNode); 54 | when(productBaseNode.getNodes()).thenReturn(nodeIterator); 55 | 56 | when(productBaseNode.getNode("awesome_shoe")).thenReturn(awesomeShoeNode); 57 | when(productBaseNode.getNode("awesome_shirt")).thenReturn(awesomeShirtNode); 58 | when(productBaseNode.getNode("awesome_jeans")).thenReturn(awesomeJeansNode); 59 | 60 | when(awesomeShoeNode.getProperty("name")).thenReturn("Awesome Shoe"); 61 | when(awesomeShoeNode.getProperty("description")).thenReturn("Description for an awesome shoe"); 62 | when(awesomeShoeNode.getProperty("price")).thenReturn("50.00"); 63 | 64 | when(awesomeShirtNode.getProperty("name")).thenReturn("Awesome Shirt"); 65 | when(awesomeShirtNode.getProperty("description")).thenReturn("Description for an awesome shirt"); 66 | when(awesomeShirtNode.getProperty("price")).thenReturn("75.00"); 67 | 68 | when(awesomeJeansNode.getProperty("name")).thenReturn("Awesome Jeans"); 69 | when(awesomeJeansNode.getProperty("description")).thenReturn("Description for an awesome jeans"); 70 | when(awesomeJeansNode.getProperty("price")).thenReturn("175.00"); 71 | 72 | PropertyIterator propertyIterator = mock(PropertyIterator.class); 73 | when(propertyIterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); 74 | when(propertyIterator.next()).thenReturn(viewProp); 75 | when(digitalAsset.getProperties()).thenReturn(propertyIterator); 76 | ``` 77 | 78 | 8. This is a lot of code just for setting up a relatively small tree. Imagine if we'd needed to setup a much larger structure. It's just too much boilerplate code. With this framework you can achieve the same thing by doing: 79 | ``` 80 | String jsonNodeStructure = " { " + 81 | "products: {" + 82 | "awesome_shoe: {" + 83 | "name: 'Awesome Shoe', " + 84 | "description: 'Description for an awesome shoe', " + 85 | "price: '50.00' " + 86 | "}," 87 | "awesome_shirt: {" + 88 | "name: 'Awesome Shirt', " + 89 | "description: 'Description for an awesome shirt', " + 90 | "price: '75.00' " + 91 | "}," 92 | "awesome_jeans: {" + 93 | "name: 'Awesome Jeans', " + 94 | "description: 'Description for awesome jeans', " + 95 | "price: '175.00' " + 96 | "}" 97 | "}" + 98 | "}"; 99 | Node productBaseNode = JcrMockingUtils.createNodesFromJsonString(jsonNodeStructure); 100 | ``` 101 | 102 | 9. Read the [Usage](#usage) section for details on how to use the framework. 103 | 104 | 105 | Usage 106 | ------ 107 | * You can include the framework as a dependency with _test_ scope in your pom.xml file: 108 | 109 | ```xml 110 | 111 | com.tacitknowledge 112 | jcr-mock 113 | 2.1.5 114 | test 115 | 116 | ``` 117 | 118 | * Then you can use the mock service on your tests: 119 | 120 | ```java 121 | String myNodeStructure = "{myAsset : " + 122 | "{ trustEntity : " + 123 | "{" + 124 | "nodeType: 'nt:unstructured'," + 125 | " view:'left'," + 126 | " binary : " + 127 | "{ " + 128 | "nodeType : 'nt:file'" + 129 | "}," + 130 | " anotherNode: " + 131 | "{ " + 132 | "attri: 'valueyes'" + 133 | "} " + 134 | "}" + 135 | "} " + 136 | "} "; 137 | Node myAssetNode = JcrMockingUtils.createNodesFromJsonString(myNodeStructure); 138 | ``` 139 | 140 | * You can also load from a json file: 141 | 142 | ```java 143 | InputStream assetsJsonFile = getClass().getResourceAsStream("/assets.json"); 144 | Node assetsNode = JcrMockingUtils.createNodesFromJsonFile(assetsJsonFile); 145 | ``` 146 | 147 | Supported Functionality 148 | ----------------------- 149 | 150 | ### JSON format Basics 151 | 152 | * JSON Objects correspond to JCR Nodes, where the name of the node is the name of the object. 153 | * JSON Properties correspond to JCR Properties. 154 | 155 | ### Node Types and Property Types 156 | 157 | * Node Types need to be explicitly declared via the jcr:primaryType property. 158 | 159 | * JSON Properties can contain the JCR Property Type information included in the value as well, for example: 160 | ``` 161 | myImportantProperty : 'type:Date' 162 | ``` 163 | 164 | * If the type information is included in the property, you can set the JCR Property value by using the 'value' special 165 | keyword: 166 | ``` 167 | myImportantProperty : 'type:String, value:The value of the property' 168 | ``` 169 | 170 | * If no type information is included in the property value, it will default as a String property. 171 | 172 | * If no property value information can be determined, the following happens: 173 | * If it's a String, the default is an empty string. 174 | * If it's a number, date or binary, an exception is thrown. 175 | 176 | ### Special Property Types 177 | 178 | * Properties of type Binary are also supported, in which case it's value will be a path to a resource file: 179 | ``` 180 | myFile : "type:Binary, value:/path/to/file.jpg" 181 | ``` 182 | * If the path to the binary doesn't exist an exception will be thrown. 183 | 184 | * For Date properties the supported format is "MM/DD/YYYY": 185 | ``` 186 | dateOfBirth : "type:Date, value:09/24/1982" 187 | ``` 188 | 189 | ### Mocked Methods 190 | 191 | * _Node.getNode()_ with relative paths. For example, this will work: 192 | 193 | ```java 194 | String jsonNodeStructure = "{" + 195 | "a: {" + 196 | "b: {" + 197 | "c: {" + 198 | "d : {" + 199 | "my_property : 'top'" + 200 | "}" + 201 | "}" + 202 | "}" + 203 | "}" + 204 | "}"; 205 | Node rootNode = JcrMockingUtils.createNodesFromJsonString(jsonNodeStructure); 206 | Node c = rootNode.getNode("a/b/c"); 207 | Node d = c.getNode("d"); 208 | ``` 209 | 210 | * _Node.getParent()_ will work all the way to the top: 211 | 212 | ```java 213 | String jsonNodeStructure = "{" + 214 | "a: {" + 215 | "b: {" + 216 | "c: {}" + 217 | "}" + 218 | "}" + 219 | "}"; 220 | 221 | Node rootNode = JcrMockingUtils.createNodesFromJsonString(jsonNodeStructure); 222 | Node c = rootNode.getNode("a/b/c"); 223 | Node a = c.getParent().getParent(); 224 | ``` 225 | 226 | Change Log 227 | ---------- 228 | * 2.1.5 - November 24, 2014 229 | * Added support for commas in property values. Fixed issue #23 230 | * 2.1.4 - December 4, 2013 231 | * Support for _property.getLong()_ method. 232 | * 2.1.3 - October 28, 2013 233 | * Added support for _node.hasNodes()_ and _node.hasProperties()_ 234 | * 2.1.2 - October 23, 2013 235 | * Added support for _propertyDefinition.isMultiple()_ and _propertyDefinition.getRequiredType()_ 236 | * 2.1.1 - October 21, 2013 237 | * Adding support for PropertyIterator (i.e. _node.getProperties()_). 238 | * Adding user friendly _toString()_ to Node and Property. 239 | * _node.hasProperty()_ supports nested property. 240 | * Added support for multivalued properties. 241 | * 2.1.0 - October 2, 2013 242 | * Adding ability to retrieve nested properties from ancestor nodes. 243 | * Fixing issue with property value returning blank for jar:primaryType. 244 | * Adding support for getPath() method for both Nodes and Properties. 245 | * Fixing issue with multiple invocations to node.getNodes() not working. 246 | * 2.0.0 - September 6, 2013 247 | * Support for node.hasProperty, node.hasProperties, node.getSession and property.getSession methods. 248 | * Removed jackrabbit dependencies. 249 | * 1.0.0 - December 11, 2012 250 | * Initial release 251 | 252 | 253 | TODOs 254 | ----- 255 | 256 | * Currently, only mocking of nodes is supported (via _MockNodeFactory_). However, it's possible to extend the framework 257 | to support writing of nodes to a real repository (for example, a _TransientRepository_) by implementing 258 | _NodeFactory_ and implementing the required methods. 259 | -------------------------------------------------------------------------------- /src/main/java/com/tacitknowledge/jcr/testing/impl/MockNodeFactory.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.impl; 2 | 3 | import com.tacitknowledge.jcr.testing.NodeFactory; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.mockito.invocation.InvocationOnMock; 6 | import org.mockito.stubbing.Answer; 7 | 8 | import javax.jcr.*; 9 | import javax.jcr.nodetype.NodeType; 10 | import javax.jcr.nodetype.PropertyDefinition; 11 | import java.io.InputStream; 12 | import java.math.BigDecimal; 13 | import java.text.ParseException; 14 | import java.text.SimpleDateFormat; 15 | import java.util.Calendar; 16 | import java.util.Date; 17 | import java.util.List; 18 | 19 | import static org.mockito.Mockito.mock; 20 | import static org.mockito.Mockito.when; 21 | 22 | 23 | /** 24 | * Factory for Mock nodes and properties 25 | * 26 | * @author Daniel Valencia (daniel@tacitknowledge.com) 27 | */ 28 | public class MockNodeFactory implements NodeFactory { 29 | 30 | private Session session = mock(Session.class); 31 | 32 | public Node createNode(Node parentNode, String nodeName, String nodeTypeName) throws RepositoryException { 33 | 34 | NodeType nodeType = mock(NodeType.class); 35 | when(nodeType.getName()).thenReturn(nodeTypeName); 36 | 37 | Node childNode = createNode(parentNode, nodeName, nodeType); 38 | 39 | return childNode; 40 | } 41 | 42 | @Override 43 | public Property createProperty(Node parent, String name, String propertyValue, int propertyType) throws RepositoryException { 44 | Property property = parent.getProperty(name); 45 | if (property == null) { 46 | property = mock(Property.class); 47 | Value value = createValueFor(property, propertyValue, propertyType); 48 | when(property.getValue()).thenReturn(value); 49 | when(property.getString()).thenReturn(propertyValue); 50 | when(property.getName()).thenReturn(name); 51 | when(property.getType()).thenReturn(propertyType); 52 | when(property.isMultiple()).thenReturn(false); 53 | when(parent.getProperty(name)).thenReturn(property); 54 | } else if (property.getValue() == null) { 55 | createValue(property, propertyValue, propertyType); 56 | } 57 | 58 | mockCommonMethods(property, parent, name); 59 | return property; 60 | } 61 | 62 | @Override 63 | public Node createNode(Node parent, String name, NodeType nodeType) throws RepositoryException { 64 | Node childNode = createNode(parent, name); 65 | if (nodeType != null) { 66 | when(childNode.isNodeType(nodeType.getName())).thenReturn(true); // Default node type 67 | when(childNode.getPrimaryNodeType()).thenReturn(nodeType); 68 | } 69 | when(childNode.getSession()).thenReturn(session); 70 | return childNode; 71 | } 72 | 73 | @Override 74 | public Node createNode(Node parent, String name) throws RepositoryException { 75 | Node childNode = null; 76 | if (parent != null) { 77 | childNode = parent.getNode(name); 78 | } 79 | if (childNode == null) { 80 | childNode = createNode(name); 81 | when(childNode.getParent()).thenReturn(parent); 82 | buildParentHierarchy(parent, childNode, name); 83 | } 84 | String path = buildPathForNode(childNode); 85 | when(childNode.getPath()).thenReturn(path); 86 | when(childNode.toString()).thenReturn(path); 87 | when(childNode.getSession()).thenReturn(session); 88 | return childNode; 89 | } 90 | 91 | @Override 92 | public Node createNode(String name) throws RepositoryException 93 | { 94 | Node childNode = mock(Node.class); 95 | when(childNode.getName()).thenReturn(name); 96 | if(StringUtils.EMPTY.equals(name)) 97 | { 98 | when(childNode.getPath()).thenReturn("/"); 99 | when(childNode.toString()).thenReturn("/"); 100 | when(session.getRootNode()).thenReturn(childNode); 101 | } 102 | 103 | when(childNode.isNode()).thenReturn(true); 104 | return childNode; 105 | } 106 | 107 | @Override 108 | public Property createMultiValuedProperty(Node parent, String name, String[] propertyValues) throws RepositoryException { 109 | Property property = parent.getProperty(name); 110 | if (property == null) { 111 | property = mock(Property.class); 112 | } 113 | if (property.getValue() == null) { 114 | Value[] values = new Value[propertyValues.length]; 115 | for(int i = 0; i < values.length; i++) { 116 | Value value = mock(Value.class); 117 | when(value.getString()).thenReturn(propertyValues[i]); 118 | when(value.getType()).thenReturn(PropertyType.STRING); 119 | values[i] = value; 120 | } 121 | when(property.getValues()).thenReturn(values); 122 | when(property.getName()).thenReturn(name); 123 | when(property.getType()).thenReturn(PropertyType.STRING); 124 | when(property.isMultiple()).thenReturn(true); 125 | when(parent.getProperty(name)).thenReturn(property); 126 | } 127 | mockCommonMethods(property, parent, name); 128 | return property; 129 | } 130 | 131 | private void mockCommonMethods(Property property, Node parent, String name) throws RepositoryException { 132 | when(property.getParent()).thenReturn(parent); 133 | when(property.getSession()).thenReturn(session); 134 | when(parent.getSession()).thenReturn(session); 135 | when(parent.hasProperty(name)).thenReturn(true); 136 | when(parent.hasProperties()).thenReturn(true); 137 | 138 | String propertyPath = parent.getPath() + "/" + name; 139 | when(property.getPath()).thenReturn(propertyPath); 140 | when(property.toString()).thenReturn(propertyPath); 141 | 142 | //adding support for getPropertyDefinition() 143 | PropertyDefinition propertyDefinition = mock(PropertyDefinition.class); 144 | when(property.getDefinition()).thenReturn(propertyDefinition); 145 | 146 | boolean isMultiple = property.isMultiple(); 147 | when(propertyDefinition.isMultiple()).thenReturn(isMultiple); 148 | 149 | int propertyType = property.getType(); 150 | when(propertyDefinition.getRequiredType()).thenReturn(propertyType); 151 | 152 | buildParentHierarchy(parent, property, name); 153 | } 154 | 155 | @Override 156 | public void createIteratorFor(Node parent, final List childNodes) throws RepositoryException { 157 | when(parent.getNodes()).thenAnswer(new Answer() 158 | { 159 | @Override 160 | public NodeIterator answer(InvocationOnMock invocationOnMock) throws Throwable 161 | { 162 | return new NodeIteratorAdapter(childNodes.iterator()); 163 | } 164 | }); 165 | 166 | when(parent.getSession()).thenReturn(session); 167 | } 168 | 169 | @Override 170 | public void createPropertyIteratorFor(Node parent, final List propertyList) throws RepositoryException { 171 | when(parent.getProperties()).thenAnswer(new Answer() { 172 | @Override 173 | public PropertyIteratorAdapter answer(InvocationOnMock invocationOnMock) throws Throwable { 174 | return new PropertyIteratorAdapter(propertyList.iterator()); 175 | } 176 | }); 177 | } 178 | 179 | @Override 180 | public Value createValueFor(Property property, String valueStr, int valueType) throws RepositoryException { 181 | Value returnValue = mock(Value.class); 182 | when(returnValue.getType()).thenReturn(valueType); 183 | 184 | switch (valueType) { 185 | case PropertyType.STRING: 186 | createStringValueFor(property, returnValue, valueStr); 187 | break; 188 | case PropertyType.BINARY: 189 | createBinaryValueFor(property, returnValue, valueStr); 190 | break; 191 | case PropertyType.BOOLEAN: 192 | createBooleanValueFor(property, returnValue, valueStr); 193 | break; 194 | case PropertyType.DOUBLE: 195 | createDoubleValueFor(property, returnValue, valueStr); 196 | break; 197 | case PropertyType.DECIMAL: 198 | createDecimalValueFor(property, returnValue, valueStr); 199 | break; 200 | case PropertyType.LONG: 201 | createLongValueFor(property, returnValue, valueStr); 202 | break; 203 | case PropertyType.DATE: 204 | createDateValueFor(property, returnValue, valueStr); 205 | // There is no break on purpose here so that Date creates also a string property 206 | default: 207 | createStringValueFor(property, returnValue, valueStr); 208 | break; 209 | } 210 | 211 | when(property.getSession()).thenReturn(session); 212 | return returnValue; 213 | } 214 | 215 | private String buildPathForNode(final Node node) throws RepositoryException 216 | { 217 | if(node != null && !StringUtils.EMPTY.equals(node.getName())) 218 | { 219 | return buildPathForNode(node.getParent()) + "/" + node.getName(); 220 | } 221 | 222 | return StringUtils.EMPTY; 223 | } 224 | 225 | private void createDateValueFor(Property property, Value returnValue, String valueStr) throws RepositoryException { 226 | Calendar calendar; 227 | try { 228 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/yyyy"); 229 | Date date = simpleDateFormat.parse(valueStr); 230 | calendar = Calendar.getInstance(); 231 | calendar.setTime(date); 232 | } catch (ParseException e) { 233 | throw new RuntimeException("Invalid format for date value: " + valueStr, e); 234 | } 235 | when(property.getDate()).thenReturn(calendar); 236 | when(returnValue.getDate()).thenReturn(calendar); 237 | } 238 | 239 | private void createLongValueFor(Property property, Value returnValue, String valueStr) throws RepositoryException { 240 | long longVal = Long.parseLong(valueStr); 241 | when(property.getLong()).thenReturn(longVal); 242 | when(returnValue.getLong()).thenReturn(longVal); 243 | } 244 | 245 | private void createDecimalValueFor(Property property, Value returnValue, String valueStr) throws RepositoryException { 246 | BigDecimal decimalValue = new BigDecimal(valueStr); 247 | when(property.getDecimal()).thenReturn(decimalValue); 248 | when(returnValue.getDecimal()).thenReturn(decimalValue); 249 | } 250 | 251 | private void createDoubleValueFor(Property property, Value returnValue, String valueStr) throws RepositoryException { 252 | double doubleVal = Double.parseDouble(valueStr); 253 | when(property.getDouble()).thenReturn(doubleVal); 254 | when(returnValue.getDouble()).thenReturn(doubleVal); 255 | } 256 | 257 | private void createStringValueFor(Property property, Value returnValue, String valueStr) throws RepositoryException { 258 | when(property.getString()).thenReturn(valueStr); 259 | when(returnValue.getString()).thenReturn(valueStr); 260 | } 261 | 262 | private void createBooleanValueFor(Property property, Value returnValue, String valueStr) throws RepositoryException { 263 | Boolean booleanVal = Boolean.valueOf(valueStr); 264 | when(property.getBoolean()).thenReturn(booleanVal); 265 | when(returnValue.getBoolean()).thenReturn(booleanVal); 266 | } 267 | 268 | private void createValue(Property property, String propertyValue, int propertyType) throws RepositoryException { 269 | Value value = createValueFor(property, propertyValue, propertyType); 270 | when(property.getValue()).thenReturn(value); 271 | } 272 | 273 | private void createBinaryValueFor(Property property, Value valueObject, String propertyValue) throws RepositoryException { 274 | InputStream binaryInputStream = getClass().getResourceAsStream(propertyValue); 275 | 276 | if (binaryInputStream == null) 277 | throw new IllegalArgumentException("Path to binary doesn't exist: " + propertyValue); 278 | 279 | Binary binary = mock(Binary.class); 280 | when(property.getBinary()).thenReturn(binary); 281 | when(binary.getStream()).thenReturn(binaryInputStream); 282 | when(valueObject.getBinary()).thenReturn(binary); 283 | } 284 | 285 | private void buildParentHierarchy(Node parent, Item childItem, String itemPath) throws RepositoryException 286 | { 287 | if (parent != null) 288 | { 289 | if(childItem.isNode()) 290 | { 291 | when(parent.getNode(itemPath)).thenReturn((Node)childItem); 292 | when(parent.hasNode(itemPath)).thenReturn(true); 293 | when(parent.hasNodes()).thenReturn(true); 294 | } 295 | else 296 | { 297 | when(parent.getProperty(itemPath)).thenReturn((Property)childItem); 298 | when(parent.hasProperty(itemPath)).thenReturn(true); 299 | when(parent.hasProperties()).thenReturn(true); 300 | } 301 | 302 | String parentName = parent.getName(); 303 | 304 | if (parentName != null) { 305 | buildParentHierarchy(parent.getParent(), childItem, parentName + "/" + itemPath); 306 | } 307 | } 308 | } 309 | 310 | } 311 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/testing/impl/MockNodeFactoryTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.testing.impl; 2 | 3 | import com.tacitknowledge.jcr.testing.NodeFactory; 4 | import com.tacitknowledge.jcr.testing.utils.PropertyTypeEnum; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import javax.jcr.*; 10 | import javax.jcr.nodetype.NodeDefinition; 11 | import javax.jcr.nodetype.NodeType; 12 | import javax.jcr.nodetype.PropertyDefinition; 13 | import java.math.BigDecimal; 14 | import java.util.ArrayList; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | 18 | import static junit.framework.Assert.*; 19 | import static org.mockito.Mockito.mock; 20 | import static org.mockito.Mockito.when; 21 | 22 | public class MockNodeFactoryTest { 23 | 24 | public static final String PROPERTY_NAME = "Name"; 25 | private MockNodeFactory nodeFactory; 26 | private Node parent; 27 | private String name; 28 | private String propertyValue; 29 | private int propertyType; 30 | private Property property; 31 | private PropertyDefinition propertyDefinition; 32 | 33 | @Before 34 | public void setUp() throws Exception { 35 | nodeFactory = new MockNodeFactory(); 36 | parent = mock(Node.class); 37 | name = "name"; 38 | propertyValue = "propertyValue"; 39 | propertyType = 1; 40 | property = mock(Property.class); 41 | propertyDefinition = mock(PropertyDefinition.class); 42 | 43 | when(propertyDefinition.getName()).thenReturn(PROPERTY_NAME); 44 | when(propertyDefinition.getRequiredType()).thenReturn(1); 45 | } 46 | 47 | @Test 48 | public void shouldCreateProperty() throws RepositoryException { 49 | nodeFactory.createProperty(parent, name, propertyValue, propertyType); 50 | 51 | Property property = parent.getProperty(name); 52 | 53 | assertNotNull(property); 54 | assertEquals(propertyType, property.getType()); 55 | assertEquals(name, property.getName()); 56 | assertTrue(parent.hasProperty(name)); 57 | assertTrue(parent.hasProperties()); 58 | 59 | Value value = property.getValue(); 60 | assertEquals(propertyValue, value.getString()); 61 | 62 | } 63 | 64 | @Test 65 | public void shouldAddValueToAlreadyCreatedProperty() throws RepositoryException { 66 | when(parent.getProperty(name)).thenReturn(property); 67 | 68 | nodeFactory.createProperty(parent, name, propertyValue, propertyType); 69 | 70 | assertNotNull(property.getValue()); 71 | assertTrue(parent.hasProperty(name)); 72 | assertTrue(parent.hasProperties()); 73 | assertNotNull(property.getSession()); 74 | } 75 | 76 | @Test 77 | public void shouldDoNothingIfPropertyIsAlreadySetup() throws RepositoryException { 78 | when(parent.getProperty(name)).thenReturn(property); 79 | Value value = mock(Value.class); 80 | when(property.getValue()).thenReturn(value); 81 | 82 | nodeFactory.createProperty(parent, name, propertyValue, propertyType); 83 | 84 | assertEquals(value, property.getValue()); 85 | assertTrue(parent.hasProperty(name)); 86 | assertTrue(parent.hasProperties()); 87 | assertNotNull(property.getSession()); 88 | } 89 | 90 | @Test 91 | public void shouldCreateNodeWithNullNodeType() throws RepositoryException { 92 | NodeType nodeType = null; 93 | Node childNode = nodeFactory.createNode(parent, name, nodeType); 94 | assertNotNull(childNode); 95 | assertNotNull(childNode.getSession()); 96 | } 97 | 98 | @Test 99 | public void shouldCreateNodeWithNodeType() throws RepositoryException { 100 | NodeType nodeType = mock(NodeType.class); 101 | Node childNode = nodeFactory.createNode(parent, name, nodeType); 102 | assertTrue(childNode.isNodeType(nodeType.getName())); 103 | assertEquals(nodeType, childNode.getPrimaryNodeType()); 104 | assertNotNull(childNode); 105 | assertNotNull(childNode.getSession()); 106 | 107 | } 108 | 109 | @Test 110 | public void shouldCreateNodeIfParentIsNull() throws RepositoryException { 111 | Node childNode = nodeFactory.createNode(null, name); 112 | assertNotNull(childNode); 113 | assertEquals(name, childNode.getName()); 114 | assertTrue(childNode.isNode()); 115 | assertNotNull(childNode.getSession()); 116 | } 117 | 118 | @Test 119 | public void shouldNotCreateChildNodeIfAlreadyExist() throws RepositoryException { 120 | Node childNode = mock(Node.class); 121 | when(parent.getNode(name)).thenReturn(childNode); 122 | Node actual = nodeFactory.createNode(parent, name); 123 | assertEquals(childNode, actual); 124 | assertNotNull(actual.getSession()); 125 | } 126 | 127 | @Test 128 | public void shouldCreateIterator() throws RepositoryException { 129 | List childNodes = new ArrayList(); 130 | nodeFactory.createIteratorFor(parent, childNodes); 131 | assertNotNull(parent.getNodes()); 132 | assertNotNull(parent.getSession()); 133 | } 134 | 135 | @Test 136 | public void shouldCreateNewIteratorOnEachCallToGetNodes() throws RepositoryException { 137 | List childNodes = new ArrayList(); 138 | nodeFactory.createIteratorFor(parent, childNodes); 139 | NodeIterator firstNodeIterator = parent.getNodes(); 140 | NodeIterator secondNodeIterator = parent.getNodes(); 141 | assertNotSame("Consecutive calls to getNodes() should return different iterator object", firstNodeIterator, secondNodeIterator); 142 | } 143 | 144 | @Test 145 | public void shouldCreatePropertyIterator() throws RepositoryException { 146 | Property firstProperty = mock(Property.class); 147 | Property secondProperty = mock(Property.class); 148 | Property thirdProperty = mock(Property.class); 149 | Property fourthProperty = mock(Property.class); 150 | Property fifthProperty = mock(Property.class); 151 | Property[] properties = {firstProperty, secondProperty, thirdProperty, fourthProperty, fifthProperty}; 152 | List propertyList = Arrays.asList(properties); 153 | nodeFactory.createPropertyIteratorFor(parent, propertyList); 154 | PropertyIterator propertyIterator = parent.getProperties(); 155 | assertNotNull(propertyIterator); 156 | 157 | //make sure we can correctly iterate over the properties 158 | int i = 0; 159 | while(propertyIterator.hasNext()) { 160 | Property propertyFromIterator = propertyIterator.nextProperty(); 161 | Property propertyFromList = propertyList.get(i); 162 | assertEquals(propertyFromList, propertyFromIterator); 163 | i++; 164 | } 165 | } 166 | 167 | @Test 168 | public void shouldCreateNewPropertyIteratorOnEachCallToGetNodes() throws RepositoryException { 169 | List childNodes = new ArrayList(); 170 | nodeFactory.createPropertyIteratorFor(parent, childNodes); 171 | PropertyIterator firstPropertyIterator = parent.getProperties(); 172 | PropertyIterator secondPropertyIterator = parent.getProperties(); 173 | assertNotSame("Consecutive calls to getProperties() should return different iterator object", firstPropertyIterator, secondPropertyIterator); 174 | } 175 | 176 | @Test 177 | public void shouldCreateBinaryValue() throws RepositoryException { 178 | nodeFactory.createValueFor(property, "/files/air_jordan.jpg", PropertyType.BINARY); 179 | 180 | assertNotNull(property.getBinary()); 181 | assertNotNull(property.getSession()); 182 | } 183 | 184 | @Test 185 | public void shouldCreateBooleanValue() throws RepositoryException { 186 | nodeFactory.createValueFor(property, "true", PropertyType.BOOLEAN); 187 | assertTrue(property.getBoolean()); 188 | assertNotNull(property.getSession()); 189 | 190 | } 191 | 192 | @Test 193 | public void shouldCreateDoubleValue() throws RepositoryException { 194 | nodeFactory.createValueFor(property, "1.0", PropertyType.DOUBLE); 195 | assertEquals(1.0, property.getDouble()); 196 | assertNotNull(property.getSession()); 197 | 198 | } 199 | 200 | @Test 201 | public void shouldCreateLongValue() throws RepositoryException { 202 | nodeFactory.createValueFor(property, "1", PropertyType.LONG); 203 | assertEquals(1L, property.getLong()); 204 | assertNotNull(property.getSession()); 205 | } 206 | 207 | @Test 208 | public void shouldCreateDecimalValue() throws RepositoryException { 209 | nodeFactory.createValueFor(property, "1.01", PropertyType.DECIMAL); 210 | assertEquals(new BigDecimal("1.01"), property.getDecimal()); 211 | assertNotNull(property.getSession()); 212 | 213 | } 214 | 215 | @Test 216 | public void shouldCreateDateValue() throws RepositoryException { 217 | nodeFactory.createValueFor(property, "12/12/2012", PropertyType.DATE); 218 | assertNotNull(property.getDate()); 219 | assertNotNull(property.getString()); 220 | assertNotNull(property.getSession()); 221 | 222 | } 223 | 224 | @Test 225 | public void shouldThrowParseExceptionWhenDateIsInvalidFormat() throws RepositoryException { 226 | try { 227 | nodeFactory.createValueFor(property, "invalidDate", PropertyType.DATE); 228 | fail("Should have thrown runtime exception"); 229 | } catch (RuntimeException re) { 230 | // runtime exception expected to happen 231 | } 232 | } 233 | 234 | 235 | @Test 236 | public void shouldCreateStringValue() throws RepositoryException { 237 | nodeFactory.createValueFor(property, "stringValue", 20); 238 | assertEquals("stringValue", property.getString()); 239 | } 240 | 241 | @Test 242 | public void shouldThrowIllegalArgumentExceptionIfBinaryDoesNotExist() throws RepositoryException { 243 | try { 244 | nodeFactory.createValueFor(property, "does not exist", PropertyType.BINARY); 245 | fail("Should have thrown illegal argument exception"); 246 | 247 | } catch (IllegalArgumentException iae) { 248 | //expected 249 | } 250 | 251 | } 252 | 253 | @Test 254 | public void shouldCreateNodeFromNodeType() throws RepositoryException { 255 | NodeType nodeType = mock(NodeType.class); 256 | PropertyDefinition[] propertyDefinitions = new PropertyDefinition[]{propertyDefinition}; 257 | String[] primaryTypeNames = new String[]{"primary"}; 258 | NodeDefinition nodeDefinition = mock(NodeDefinition.class); 259 | NodeType mockNodeType = mock(NodeType.class); 260 | NodeDefinition[] nodeDefinitions = new NodeDefinition[]{nodeDefinition}; 261 | NodeDefinition[] emptyDefinitions = new NodeDefinition[]{}; 262 | 263 | when(nodeType.getPropertyDefinitions()).thenReturn(propertyDefinitions); 264 | when(nodeDefinition.getDeclaringNodeType()).thenReturn(mockNodeType); 265 | when(nodeDefinition.getRequiredPrimaryTypeNames()).thenReturn(primaryTypeNames); 266 | when(nodeType.getChildNodeDefinitions()).thenReturn(nodeDefinitions).thenReturn(emptyDefinitions); 267 | 268 | Node childNode = nodeFactory.createNode(parent, name, "nodeType"); 269 | 270 | assertNotNull(childNode); 271 | assertNotNull(childNode.getSession()); 272 | 273 | } 274 | 275 | @Test 276 | public void callToGetPathShouldReturnAbsolutePath() throws RepositoryException 277 | { 278 | NodeFactory myNodeFactory = new MockNodeFactory(); 279 | Node rootNode = myNodeFactory.createNode(StringUtils.EMPTY); 280 | 281 | Node firstLevelNode = myNodeFactory.createNode(rootNode, "firstLevel"); 282 | Node secondLevelNode = myNodeFactory.createNode(firstLevelNode, "secondLevel"); 283 | 284 | myNodeFactory.createProperty(secondLevelNode, "thirdLevelProp", "some value", PropertyTypeEnum.STRING.getPropertyType()); 285 | Property thirdLevelProp = secondLevelNode.getProperty("thirdLevelProp"); 286 | 287 | assertEquals("Expected path to be /", "/", rootNode.getPath()); 288 | assertEquals("Expected path to be /", "/", rootNode.toString()); 289 | assertEquals("Expected path to be /firstLevel", "/firstLevel", firstLevelNode.getPath()); 290 | assertEquals("Expected path to be /firstLevel", "/firstLevel", firstLevelNode.toString()); 291 | assertEquals("Expected path to be /firstLevel/secondLevel", "/firstLevel/secondLevel", secondLevelNode.getPath()); 292 | assertEquals("Expected path to be /firstLevel/secondLevel", "/firstLevel/secondLevel", secondLevelNode.toString()); 293 | assertEquals("Expected path to be /firstLevel/secondLevel/thirdLevelProp", "/firstLevel/secondLevel/thirdLevelProp", thirdLevelProp.getPath()); 294 | assertEquals("Expected path to be /firstLevel/secondLevel/thirdLevelProp", "/firstLevel/secondLevel/thirdLevelProp", thirdLevelProp.toString()); 295 | } 296 | 297 | @Test 298 | public void shouldRetrievePropertyFromAllAscendantNodes() throws RepositoryException 299 | { 300 | Node rootNode = nodeFactory.createNode(StringUtils.EMPTY); 301 | 302 | Node firstLevelNode = nodeFactory.createNode(rootNode, "firstLevel"); 303 | Node secondLevelNode = nodeFactory.createNode(firstLevelNode, "secondLevel"); 304 | 305 | nodeFactory.createProperty(secondLevelNode, "thirdLevelProp", "some value", PropertyTypeEnum.STRING.getPropertyType()); 306 | 307 | Property thirdLevelProp = firstLevelNode.getProperty("secondLevel/thirdLevelProp"); 308 | assertNotNull("Expected property to be not null", thirdLevelProp); 309 | assertEquals("Expected property value to be 'some value'", "some value", thirdLevelProp.getString()); 310 | assertEquals("Expected property value to be 'some value'", "some value", thirdLevelProp.getValue().getString()); 311 | assertEquals("Expected hasProperty() to return true", true, firstLevelNode.hasProperty("secondLevel/thirdLevelProp")); 312 | 313 | Property propertyFromRootNode = rootNode.getProperty("firstLevel/secondLevel/thirdLevelProp"); 314 | assertNotNull("Expected property to be not null", propertyFromRootNode); 315 | assertEquals("Expected property value to be 'some value'", "some value", propertyFromRootNode.getString()); 316 | assertEquals("Expected property value to be 'some value'", "some value", propertyFromRootNode.getValue().getString()); 317 | assertEquals("Expected hasProperty() to return true", true, rootNode.hasProperty("firstLevel/secondLevel/thirdLevelProp")); 318 | assertEquals("Expected hasProperty() to return false", false, rootNode.hasProperty("secondLevel/thirdLevelProp")); 319 | } 320 | 321 | @Test 322 | public void shouldRetrieveNodeFromAllAscendantNodes() throws RepositoryException 323 | { 324 | Node rootNode = nodeFactory.createNode(StringUtils.EMPTY); 325 | 326 | Node firstLevelNode = nodeFactory.createNode(rootNode, "firstLevel"); 327 | Node secondLevelNode = nodeFactory.createNode(firstLevelNode, "secondLevel"); 328 | Node thirdLevelNode = nodeFactory.createNode(secondLevelNode, "thirdLevel"); 329 | 330 | assertTrue("Expected root node to have firstLevel/secondLevel/thirdLevel)", rootNode.hasNode("firstLevel/secondLevel/thirdLevel")); 331 | assertFalse("Expected root node to NOT have secondLevel/thirdLevel)", rootNode.hasNode("secondLevel/thirdLevel")); 332 | assertTrue("Expected root node to have firstLevel/secondLevel)", rootNode.hasNode("firstLevel/secondLevel")); 333 | assertEquals("Expected root node to access firstLevel/secondLevel/thirdLevel)", rootNode.getNode("firstLevel/secondLevel/thirdLevel"), thirdLevelNode); 334 | assertEquals("Expected root node to access firstLevel/secondLevel)", rootNode.getNode("firstLevel/secondLevel"), secondLevelNode); 335 | 336 | assertTrue("Expected first level node to have secondLevel/thirdLevel)", firstLevelNode.hasNode("secondLevel/thirdLevel")); 337 | assertFalse("Expected first level node to NOT have firstLevel/secondLevel/thirdLevel)", firstLevelNode.hasNode("firstLevel/secondLevel/thirdLevel")); 338 | assertTrue("Expected first level node to have secondLevel)", firstLevelNode.hasNode("secondLevel")); 339 | assertEquals("Expected first level node to access secondLevel/thirdLevel)", firstLevelNode.getNode("secondLevel/thirdLevel"), thirdLevelNode); 340 | assertEquals("Expected first level node to access secondLevel)", firstLevelNode.getNode("secondLevel"), secondLevelNode); 341 | } 342 | 343 | @Test 344 | public void shouldSupportPropertyDefinition() throws RepositoryException { 345 | Node rootNode = nodeFactory.createNode(StringUtils.EMPTY); 346 | 347 | Property singleStringProperty = nodeFactory.createProperty(rootNode, "singleStringProperty", "singleValue", PropertyType.STRING); 348 | PropertyDefinition singleStringPropertyDef = singleStringProperty.getDefinition(); 349 | assertNotNull(singleStringPropertyDef); 350 | assertFalse(singleStringPropertyDef.isMultiple()); 351 | assertEquals(PropertyType.STRING, singleStringPropertyDef.getRequiredType()); 352 | 353 | Property singleLongProperty = nodeFactory.createProperty(rootNode, "singleLongProperty", "5", PropertyType.LONG); 354 | PropertyDefinition singleLongPropertyDef = singleLongProperty.getDefinition(); 355 | assertNotNull(singleLongPropertyDef); 356 | assertFalse(singleLongPropertyDef.isMultiple()); 357 | assertEquals(PropertyType.LONG, singleLongPropertyDef.getRequiredType()); 358 | 359 | String[] values = {"value1", "value2"}; 360 | Property multipleStringProperty = nodeFactory.createMultiValuedProperty(rootNode, "multipleStringProperty", values); 361 | PropertyDefinition multipleStringPropertyDef = multipleStringProperty.getDefinition(); 362 | assertNotNull(multipleStringPropertyDef); 363 | assertTrue(multipleStringPropertyDef.isMultiple()); 364 | assertEquals(PropertyType.STRING, multipleStringPropertyDef.getRequiredType()); 365 | } 366 | 367 | 368 | @Test 369 | public void shouldSupportHasNodes() throws RepositoryException { 370 | 371 | Node rootNode = nodeFactory.createNode(StringUtils.EMPTY); 372 | 373 | Node firstLevelNode = nodeFactory.createNode(rootNode, "firstLevel"); 374 | assertFalse(firstLevelNode.hasNodes()); 375 | 376 | // give it a child 377 | @SuppressWarnings("unused") 378 | Node secondLevelNode = nodeFactory.createNode(firstLevelNode, "secondLevel"); 379 | assertTrue(firstLevelNode.hasNodes()); 380 | } 381 | 382 | @Test 383 | public void shouldSupportHasProperties() throws RepositoryException { 384 | 385 | Node rootNode = nodeFactory.createNode(StringUtils.EMPTY); 386 | 387 | Node firstLevelNode = nodeFactory.createNode(rootNode, "firstLevel"); 388 | assertFalse(firstLevelNode.hasProperties()); 389 | 390 | nodeFactory.createProperty(firstLevelNode, "foo", "bar", PropertyTypeEnum.STRING.getPropertyType()); 391 | assertTrue(firstLevelNode.hasProperties()); 392 | 393 | } 394 | } 395 | -------------------------------------------------------------------------------- /src/test/java/com/tacitknowledge/jcr/mocking/JcrMockServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.tacitknowledge.jcr.mocking; 2 | 3 | import com.tacitknowledge.jcr.mocking.impl.JsonMockService; 4 | import com.tacitknowledge.jcr.testing.NodeFactory; 5 | import com.tacitknowledge.jcr.testing.impl.MockNodeFactory; 6 | import com.tacitknowledge.jcr.testing.utils.JcrTestingUtils; 7 | 8 | import org.apache.commons.collections.IteratorUtils; 9 | import org.apache.commons.io.IOUtils; 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.junit.BeforeClass; 12 | import org.junit.Test; 13 | 14 | import javax.jcr.*; 15 | 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | import java.util.List; 19 | import java.util.NoSuchElementException; 20 | 21 | import static org.junit.Assert.*; 22 | import static org.mockito.Mockito.mock; 23 | 24 | /** 25 | * @author Daniel Valencia (daniel@tacitknowledge.com) 26 | */ 27 | public class JcrMockServiceTest { 28 | 29 | private static JcrMockService mockService; 30 | public static final String JSON_NODE_DEFINITION_WITH_NODE_TYPES = 31 | "{" + 32 | " ac2d111: {" + 33 | " trustEntity: 'type:String'," + 34 | " view: 'type:String'," + 35 | " binary: {" + 36 | " nodeType: 'nt:file'," + 37 | " 'jcr:content': {" + 38 | " 'jcr:data': 'type:Binary, value:/files/air_jordan.jpg'" + 39 | " }" + 40 | " }" + 41 | " }" + 42 | "}"; 43 | 44 | public static final String JSON_NODE_DEFINITION_WITH_TWO_NODES = 45 | "{" + 46 | " ac2d111: {" + 47 | " trustEntity: 'type:String'," + 48 | " view: 'type:String'," + 49 | " binary: {" + 50 | " nodeType: 'nt:file'" + 51 | " }," + 52 | " anotherNode: {" + 53 | " attri: 'valueyes'" + 54 | " }" + 55 | " }" + 56 | "} "; 57 | 58 | @BeforeClass 59 | public static void setup() throws RepositoryException, IOException { 60 | NodeFactory mockFactory = new MockNodeFactory(); 61 | mockService = new JsonMockService(mockFactory); 62 | } 63 | 64 | @Test 65 | public void testJcrNodeServiceWithParentNode() throws RepositoryException { 66 | String jsonNodeDefinition = 67 | "{" + 68 | " content: {" + 69 | " dpils: {" + 70 | " testProperty: 'myvalue'" + 71 | " }" + 72 | " }" + 73 | "}"; 74 | 75 | Node parentNode = mock(Node.class); 76 | mockService.fromString(parentNode, jsonNodeDefinition); 77 | 78 | assertNodeContents(parentNode); 79 | } 80 | 81 | @Test 82 | public void shouldAddItemTypeInformationToNodeStructure() throws RepositoryException { 83 | 84 | Node parentNode = mock(Node.class); 85 | mockService.fromString(parentNode, JSON_NODE_DEFINITION_WITH_NODE_TYPES); 86 | 87 | Node assetNode = parentNode.getNode("ac2d111"); 88 | assertNotNull(assetNode); 89 | 90 | JcrTestingUtils.assertProperty(assetNode.getProperty("trustEntity"), PropertyType.STRING, StringUtils.EMPTY); 91 | JcrTestingUtils.assertProperty(assetNode.getProperty("view"), PropertyType.STRING, StringUtils.EMPTY); 92 | 93 | Node binary = assetNode.getNode("binary"); 94 | assertNotNull("Binary folder should not be null", binary); 95 | 96 | Node jcrContent = binary.getNode("jcr:content"); 97 | JcrTestingUtils.assertPropertyType(jcrContent.getProperty("jcr:data"), PropertyType.BINARY); 98 | } 99 | 100 | @Test 101 | public void shouldCreateFullJsonStructureFromFile() throws IOException, RepositoryException { 102 | String jsonString = IOUtils.toString(getClass().getResourceAsStream("/mock-nodes.json")); 103 | assertNotNull(jsonString); 104 | 105 | Node parentNode = mock(Node.class); 106 | mockService.fromString(parentNode, jsonString); 107 | 108 | Node ac2d111 = parentNode.getNode("ac2d111"); 109 | Node ac2d112 = parentNode.getNode("ac2d112"); 110 | Node ac2d113 = parentNode.getNode("ac2d113"); 111 | 112 | assertNotNull(ac2d111); 113 | assertNotNull(ac2d112); 114 | assertNotNull(ac2d113); 115 | } 116 | 117 | @Test 118 | public void testDeepHierarchies() throws RepositoryException { 119 | 120 | 121 | Node parentNode = mock(Node.class); 122 | mockService.fromString(parentNode, JSON_NODE_DEFINITION_WITH_NODE_TYPES); 123 | 124 | Node ac2d111Node = parentNode.getNode("ac2d111"); 125 | 126 | Node binaryNode = parentNode.getNode("ac2d111/binary"); 127 | assertEquals("Expected both nodes to be the same", binaryNode, ac2d111Node.getNode("binary")); 128 | 129 | Node jcrContentNode = parentNode.getNode("ac2d111/binary/jcr:content"); 130 | assertEquals("Expected both nodes to be the same", jcrContentNode, binaryNode.getNode("jcr:content")); 131 | 132 | 133 | assertNotNull("Binary node should not be null", jcrContentNode); 134 | 135 | } 136 | 137 | @Test(expected = NoSuchElementException.class) 138 | public void shouldReturnWorkingNodeIterator() throws RepositoryException { 139 | 140 | Node parentNode = mock(Node.class); 141 | 142 | mockService.fromString(parentNode, JSON_NODE_DEFINITION_WITH_TWO_NODES); 143 | 144 | Node ac2d111Node = parentNode.getNode("ac2d111"); 145 | 146 | NodeIterator childNodeIterator = ac2d111Node.getNodes(); 147 | 148 | assertTrue("Should have one node", childNodeIterator.hasNext()); 149 | assertEquals("Binary node should exist", ac2d111Node.getNode("binary"), childNodeIterator.nextNode()); 150 | 151 | assertTrue("Should not have anymore nodes", childNodeIterator.hasNext()); 152 | assertEquals("anotherNode node should exist", ac2d111Node.getNode("anotherNode"), childNodeIterator.nextNode()); 153 | 154 | assertFalse("Should not have anymore nodes", childNodeIterator.hasNext()); 155 | 156 | childNodeIterator.nextNode(); 157 | 158 | fail("An exception should have been thrown"); 159 | } 160 | 161 | @Test(expected = NoSuchElementException.class) 162 | public void iteratorShouldWorkWithNodesWithoutChildren() throws RepositoryException { 163 | 164 | 165 | Node parentNode = mock(Node.class); 166 | 167 | mockService.fromString(parentNode, JSON_NODE_DEFINITION_WITH_TWO_NODES); 168 | 169 | Node ac2d111Node = parentNode.getNode("ac2d111"); 170 | 171 | NodeIterator anotherNodeIterator = ac2d111Node.getNode("anotherNode").getNodes(); 172 | 173 | assertFalse("Should not have children", anotherNodeIterator.hasNext()); 174 | 175 | anotherNodeIterator.nextNode(); 176 | fail("An exception should have been thrown"); 177 | } 178 | 179 | @Test 180 | public void shouldSetBinaryValue() throws RepositoryException { 181 | String jsonNodeDefinitionWithNodeTypes = 182 | "{" + 183 | " ac2d111: {" + 184 | " trustEntity: 'type:String'," + 185 | " view: 'type:String'," + 186 | " binary: {" + 187 | " nodeType: 'nt:file'," + 188 | " 'jcr:content': {" + 189 | " 'jcr:data': 'type:Binary, value:/files/air_jordan.jpg'" + 190 | " }" + 191 | " }," + 192 | " anotherNode: {" + 193 | " attri: 'valueyes'" + 194 | " }" + 195 | " }" + 196 | "} "; 197 | 198 | Node parentNode = mock(Node.class); 199 | 200 | mockService.fromString(parentNode, jsonNodeDefinitionWithNodeTypes); 201 | 202 | Node ac2d111Node = parentNode.getNode("ac2d111"); 203 | 204 | Node jcrContentNode = ac2d111Node.getNode("binary/jcr:content"); 205 | 206 | Property jcrData = jcrContentNode.getProperty("jcr:data"); 207 | 208 | Binary airJordanBinary = jcrData.getValue().getBinary(); 209 | InputStream airJordanInputStream = airJordanBinary.getStream(); 210 | 211 | assertNotNull("Binary should not be null", airJordanBinary); 212 | assertNotNull("InputStream Should not be null either", airJordanInputStream); 213 | } 214 | 215 | @Test 216 | public void shouldCreateNodeStructureWithoutPassingAParentNode() throws RepositoryException { 217 | String jsonNodeStructure = 218 | "{" + 219 | " products: {" + 220 | " productA: {" + 221 | " name: 'Air Jordan'," + 222 | " confidentiality: 'Bronze'," + 223 | " digitalAssets: {" + 224 | " asset1: {" + 225 | " mimeType: 'jpg'," + 226 | " contentType: 'photography'," + 227 | " binary: 'type:Binary, value:/files/air_jordan.jpg'" + 228 | " }" + 229 | " }" + 230 | " }" + 231 | " }" + 232 | "}"; 233 | 234 | Node rootNode = mockService.fromString(jsonNodeStructure); 235 | assertNotNull(rootNode); 236 | 237 | Node productsNode = rootNode.getNode("products"); 238 | 239 | assertEquals("Expecting the node be named 'products' but is : " + productsNode.getName(), "products", productsNode.getName()); 240 | 241 | Node productAnode = productsNode.getNode("productA"); 242 | assertNotNull(productAnode); 243 | JcrTestingUtils.assertIteratorCount(productAnode.getNodes(), 1); 244 | 245 | 246 | Node digitalAssetsNode = productAnode.getNode("digitalAssets"); 247 | JcrTestingUtils.assertIteratorCount(digitalAssetsNode.getNodes(), 1); 248 | 249 | Node asset1Node = productAnode.getNode("digitalAssets/asset1"); 250 | Property mimeTypeProperty = asset1Node.getProperty("mimeType"); 251 | assertEquals("Expected a jpg", "jpg", mimeTypeProperty.getValue().getString()); 252 | 253 | } 254 | 255 | @Test 256 | public void shouldHandleReferences() throws IOException, RepositoryException { 257 | String nodeStructureWithArrays = IOUtils.toString(getClass().getResourceAsStream("/asset_list.json")); 258 | Node rootNode = mockService.fromString(nodeStructureWithArrays); 259 | 260 | assertNotNull("Expected nodestructure to be not null", rootNode); 261 | 262 | Node productsParentNode = rootNode.getNode("products"); 263 | assertNotNull("Expected products node to be not null", productsParentNode); 264 | 265 | List productNodeList = IteratorUtils.toList(productsParentNode.getNodes()); 266 | 267 | Node firstProduct = productNodeList.get(0); 268 | List digitalAssetList = IteratorUtils.toList(firstProduct.getNode("digitalAssets").getNodes()); 269 | 270 | Node digitalAsset = digitalAssetList.get(0); 271 | 272 | Property binaryReference = digitalAsset.getProperty("binary_ref"); 273 | assertEquals("Expected 123456", "123456", binaryReference.getString()); 274 | assertEquals("Expected Reference", PropertyType.REFERENCE, binaryReference.getType()); 275 | } 276 | 277 | 278 | private void assertNodeContents(Node parentNode) throws RepositoryException { 279 | Node contentNode = parentNode.getNode("content"); 280 | assertNotNull("Node is null", contentNode); 281 | assertEquals("Names don't match", "content", contentNode.getName()); 282 | 283 | Node dpilsNode = contentNode.getNode("dpils"); 284 | assertNotNull("Node is null", dpilsNode); 285 | assertEquals("Names don't match", "dpils", dpilsNode.getName()); 286 | 287 | Property testProperty = dpilsNode.getProperty("testProperty"); 288 | assertNotNull("Peoperty is null", testProperty); 289 | assertEquals("Property Name doesn't match", "testProperty", testProperty.getName()); 290 | assertEquals("Property Value doesn't match", "myvalue", testProperty.getString()); 291 | } 292 | 293 | @Test 294 | public void shouldBeAbleToIterateOnNodesMultipleTimes() throws RepositoryException { 295 | String jsonNodeStructure = 296 | "{" + 297 | " products: {" + 298 | " productA: {" + 299 | " name: 'Air Jordan'," + 300 | " confidentiality: 'Bronze'," + 301 | " someNode: {}," + 302 | " digitalAssets: {" + 303 | " asset1: {" + 304 | " mimeType: 'jpg'," + 305 | " contentType: 'photography'," + 306 | " binary: 'type:Binary, value:/files/air_jordan.jpg'" + 307 | " }" + 308 | " }" + 309 | " }" + 310 | " }" + 311 | "}"; 312 | 313 | Node rootNode = mockService.fromString(jsonNodeStructure); 314 | assertNotNull(rootNode); 315 | 316 | Node productANode = rootNode.getNode("products/productA"); 317 | 318 | assertNotNull(productANode); 319 | 320 | //Call to JcrTestingUtils.assertIteratorCount will traverse the iterator 321 | NodeIterator productAIterator = productANode.getNodes(); 322 | JcrTestingUtils.assertIteratorCount(productAIterator, 2); 323 | 324 | //Traversing the iterator again should result in no nodes found 325 | JcrTestingUtils.assertIteratorCount(productAIterator, 0); 326 | 327 | //Calling getNodes() should return a fresh iterator which we can use to traverse the node tree again. 328 | JcrTestingUtils.assertIteratorCount(productANode.getNodes(), 2); 329 | } 330 | 331 | @Test 332 | public void getPathShouldWorkForBothNodesAndProperties() throws RepositoryException { 333 | String jsonNodeStructure = 334 | "{" + 335 | " products: {" + 336 | " productA: {" + 337 | " name: 'Air Jordan'," + 338 | " confidentiality: 'Bronze'," + 339 | " someNode: {}," + 340 | " digitalAssets: {" + 341 | " asset1: {" + 342 | " mimeType: 'jpg'," + 343 | " contentType: 'photography'," + 344 | " binary: 'type:Binary, value:/files/air_jordan.jpg'" + 345 | " }" + 346 | " }" + 347 | " }" + 348 | " }" + 349 | "}"; 350 | 351 | Node rootNode = mockService.fromString(jsonNodeStructure); 352 | 353 | assertEquals("Expected path to be root /", "/", rootNode.getPath()); 354 | assertEquals("Expected path to be /products", "/products", rootNode.getNode("products").getPath()); 355 | assertEquals("Expected path to be /products/productA", "/products/productA", rootNode.getNode("products/productA").getPath()); 356 | Property mimeType = rootNode.getNode("products/productA/digitalAssets/asset1").getProperty("mimeType"); 357 | assertEquals("Expected path to be /products/productA/digitalAssets/asset1/mimeType", "/products/productA/digitalAssets/asset1/mimeType", mimeType.getPath()); 358 | } 359 | 360 | @Test 361 | public void shouldReturnCorrectPrimaryTypePropertyValueAsString() throws RepositoryException { 362 | String jsonNodeStructureWithPrimaryType = 363 | "{" + 364 | " ac2d111: {" + 365 | " trustEntity: 'type:String'," + 366 | " view: 'type:String'," + 367 | " binary: {" + 368 | " 'jcr:primaryType': 'nt:file'" + 369 | " }," + 370 | " anotherNode: {" + 371 | " attri: 'valueyes'" + 372 | " }" + 373 | " }" + 374 | "} "; 375 | 376 | Node rootNode = mockService.fromString(jsonNodeStructureWithPrimaryType); 377 | 378 | Node binaryNode = rootNode.getNode("ac2d111/binary"); 379 | Property primaryTypeProperty = binaryNode.getProperty("jcr:primaryType"); 380 | 381 | assertNotNull("Primary type property should not be null", primaryTypeProperty); 382 | assertEquals("Expected primary type to be nt:file", "nt:file", primaryTypeProperty.getString()); 383 | assertEquals("Expected primary type to be nt:file", "nt:file", primaryTypeProperty.getValue().getString()); 384 | } 385 | 386 | @Test 387 | public void shouldBeAbleToRetrieveNestedPropertyFromAncestors() throws RepositoryException { 388 | String jsonNodeStructure = 389 | "{" + 390 | " products: {" + 391 | " productA: {" + 392 | " name: 'Air Jordan'," + 393 | " confidentiality: 'Bronze'," + 394 | " someNode: {}," + 395 | " digitalAssets: {" + 396 | " asset1: {" + 397 | " mimeType: 'jpg'," + 398 | " contentType: 'photography'," + 399 | " binary: 'type:Binary, value:/files/air_jordan.jpg'" + 400 | " }" + 401 | " }" + 402 | " }" + 403 | " }" + 404 | "}"; 405 | 406 | Node rootNode = mockService.fromString(jsonNodeStructure); 407 | assertNotNull(rootNode); 408 | 409 | Property productAName = rootNode.getProperty("products/productA/name"); 410 | 411 | assertNotNull(productAName); 412 | assertEquals("Expected name to be 'Air Jordan'", "Air Jordan", productAName.getString()); 413 | 414 | Node digitalAssetsNode = rootNode.getNode("products/productA/digitalAssets"); 415 | Property contentTypeProperty = digitalAssetsNode.getProperty("asset1/contentType"); 416 | 417 | assertNotNull(contentTypeProperty); 418 | assertEquals("Expected content type to be 'photography'", "photography", contentTypeProperty.getValue().getString()); 419 | } 420 | 421 | @Test 422 | public void shouldReadMultiValuedProperty() throws RepositoryException { 423 | String jsonNodeStructure = 424 | "{" + 425 | " ac2d111: {" + 426 | " skills: [\"skill1\", \"skill2\", \"skill3\"]" + 427 | " }" + 428 | "}"; 429 | String propertyName = "ac2d111/skills"; 430 | Node rootNode = mockService.fromString(jsonNodeStructure); 431 | assertTrue(rootNode.hasProperty(propertyName)); 432 | assertNotNull(rootNode.getProperty(propertyName)); 433 | Property property = rootNode.getProperty(propertyName); 434 | assertTrue(property.isMultiple()); 435 | assertNotNull(property.getValues()); 436 | Value[] values = property.getValues(); 437 | assertEquals(values.length, 3); 438 | assertEquals(values[0].getString(), "skill1"); 439 | assertEquals(values[1].getString(), "skill2"); 440 | assertEquals(values[2].getString(), "skill3"); 441 | } 442 | 443 | /** 444 | * issue #23 test commas in a property value 445 | * @throws RepositoryException 446 | */ 447 | @Test 448 | public void shouldReadPropertiesWithCommas() throws RepositoryException{ 449 | String jsonNodeStructure = 450 | "{"+ 451 | "etc: {"+ 452 | "sni-asset: {"+ 453 | "test: {"+ 454 | "\"jcr:content\": {"+ 455 | "nodeType: \"cq:PageContent\","+ 456 | "test: \"Here's a test with a comma,\""+ 457 | "}"+ 458 | "}"+ 459 | "}"+ 460 | "}"+ 461 | "}"; 462 | 463 | Node rootNode = mockService.fromString(jsonNodeStructure); 464 | Node jcr_contentNode = rootNode.getNode("etc/sni-asset/test/jcr:content"); 465 | Property prop = jcr_contentNode.getProperty("test"); 466 | assertEquals(prop.getString(), "Here\'s a test with a comma,"); 467 | } 468 | 469 | } 470 | --------------------------------------------------------------------------------