From 2101191b8b7e3ebe1d72a2932dd6e434f5500a06 Mon Sep 17 00:00:00 2001 From: Julien Roy Date: Sun, 15 Dec 2019 14:53:19 +0100 Subject: [PATCH] Implement SoftAssertions (#58) --- .../assertj/db/api/AbstractColumnAssert.java | 2 +- .../org/assertj/db/api/AbstractRowAssert.java | 2 +- .../db/api/AbstractSoftAssertions.java | 65 +++++++++ .../java/org/assertj/db/api/ChangeAssert.java | 2 +- .../assertj/db/api/ChangeColumnAssert.java | 6 +- .../assertj/db/api/ProxifyPositionResult.java | 125 ++++++++++++++++++ .../org/assertj/db/api/SoftAssertions.java | 71 ++++++++++ .../java/org/assertj/db/api/SoftProxies.java | 81 ++++++++++++ .../impl/AssertionsOnValueCondition.java | 2 + .../org/assertj/db/navigation/Position.java | 18 ++- .../db/navigation/PositionWithChanges.java | 21 +-- .../navigation/PositionWithColumnsChange.java | 16 ++- .../db/navigation/PositionWithPoints.java | 9 +- .../java/org/assertj/db/util/Proxies.java | 46 +++++++ .../assertj/db/api/SoftAssertions_Test.java | 113 ++++++++++++++++ .../org/assertj/db/util/Proxies_Test.java | 65 +++++++++ 16 files changed, 614 insertions(+), 30 deletions(-) create mode 100644 src/main/java/org/assertj/db/api/AbstractSoftAssertions.java create mode 100644 src/main/java/org/assertj/db/api/ProxifyPositionResult.java create mode 100644 src/main/java/org/assertj/db/api/SoftAssertions.java create mode 100644 src/main/java/org/assertj/db/api/SoftProxies.java create mode 100644 src/main/java/org/assertj/db/util/Proxies.java create mode 100644 src/test/java/org/assertj/db/api/SoftAssertions_Test.java create mode 100644 src/test/java/org/assertj/db/util/Proxies_Test.java diff --git a/src/main/java/org/assertj/db/api/AbstractColumnAssert.java b/src/main/java/org/assertj/db/api/AbstractColumnAssert.java index d1363bfa..22bcc82e 100644 --- a/src/main/java/org/assertj/db/api/AbstractColumnAssert.java +++ b/src/main/java/org/assertj/db/api/AbstractColumnAssert.java @@ -55,7 +55,7 @@ public abstract class AbstractColumnAssert, A extend /** * Column on which do the assertion. */ - private final Column column; + protected final Column column; /** * Constructor. diff --git a/src/main/java/org/assertj/db/api/AbstractRowAssert.java b/src/main/java/org/assertj/db/api/AbstractRowAssert.java index d6b66ce2..b85e46d5 100644 --- a/src/main/java/org/assertj/db/api/AbstractRowAssert.java +++ b/src/main/java/org/assertj/db/api/AbstractRowAssert.java @@ -59,7 +59,7 @@ public abstract class AbstractRowAssert, A extends A /** * Row on which do the assertion. */ - private final Row row; + protected final Row row; /** * Constructor. diff --git a/src/main/java/org/assertj/db/api/AbstractSoftAssertions.java b/src/main/java/org/assertj/db/api/AbstractSoftAssertions.java new file mode 100644 index 00000000..d6d7172e --- /dev/null +++ b/src/main/java/org/assertj/db/api/AbstractSoftAssertions.java @@ -0,0 +1,65 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2012-2016 the original author or authors. + */ +package org.assertj.db.api; + +import org.assertj.core.internal.Failures; +import org.assertj.core.util.Lists; + +import java.util.List; + +/** + * Base class of AssertJ-DB SoftAssertions. + * + * @author Julien Roy + */ +public class AbstractSoftAssertions { + + protected final SoftProxies proxies = new SoftProxies(); + + public V proxy(Class assertClass, Class actualClass, T actual) { + return this.proxies.create(assertClass, actualClass, actual); + } + + public void fail(String failureMessage) { + AssertionError error = Failures.instance().failure(failureMessage); + this.proxies.collectError(error); + } + + public void fail(String failureMessage, Object... args) { + AssertionError error = Failures.instance().failure(String.format(failureMessage, args)); + this.proxies.collectError(error); + } + + public void fail(String failureMessage, Throwable realCause) { + AssertionError error = Failures.instance().failure(failureMessage); + error.initCause(realCause); + this.proxies.collectError(error); + } + + public void failBecauseExceptionWasNotThrown(Class throwableClass) { + this.shouldHaveThrown(throwableClass); + } + + public void shouldHaveThrown(Class throwableClass) { + AssertionError error = Failures.instance().expectedThrowableNotThrown(throwableClass); + this.proxies.collectError(error); + } + + public List errorsCollected() { + return Lists.newArrayList(this.proxies.errorsCollected()); + } + + public boolean wasSuccess() { + return this.proxies.wasSuccess(); + } +} diff --git a/src/main/java/org/assertj/db/api/ChangeAssert.java b/src/main/java/org/assertj/db/api/ChangeAssert.java index d8da1265..bf3480b2 100644 --- a/src/main/java/org/assertj/db/api/ChangeAssert.java +++ b/src/main/java/org/assertj/db/api/ChangeAssert.java @@ -44,7 +44,7 @@ public class ChangeAssert /** * The actual change on which the assertion is. */ - private final Change change; + protected final Change change; /** * Position of navigation to row. diff --git a/src/main/java/org/assertj/db/api/ChangeColumnAssert.java b/src/main/java/org/assertj/db/api/ChangeColumnAssert.java index a1d236ae..4c8ed168 100644 --- a/src/main/java/org/assertj/db/api/ChangeColumnAssert.java +++ b/src/main/java/org/assertj/db/api/ChangeColumnAssert.java @@ -43,16 +43,16 @@ public class ChangeColumnAssert /** * The name of the column. */ - private final String columnName; + protected final String columnName; /** * The actual value at start point. */ - private final Value valueAtStartPoint; + protected final Value valueAtStartPoint; /** * The actual value at end point. */ - private final Value valueAtEndPoint; + protected final Value valueAtEndPoint; /** * Position of navigation to row. diff --git a/src/main/java/org/assertj/db/api/ProxifyPositionResult.java b/src/main/java/org/assertj/db/api/ProxifyPositionResult.java new file mode 100644 index 00000000..35b28861 --- /dev/null +++ b/src/main/java/org/assertj/db/api/ProxifyPositionResult.java @@ -0,0 +1,125 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2012-2016 the original author or authors. + */ +package org.assertj.db.api; + +import org.assertj.core.api.ObjectArrayAssert; +import org.assertj.core.internal.cglib.proxy.MethodInterceptor; +import org.assertj.core.internal.cglib.proxy.MethodProxy; +import org.assertj.core.util.Arrays; +import org.assertj.db.type.Change; +import org.assertj.db.type.Column; +import org.assertj.db.type.Row; +import org.assertj.db.type.Value; + +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import static org.assertj.db.util.Proxies.isProxified; +import static org.assertj.db.util.Proxies.unProxy; + +/** + * Method interceptor that proxify result of assertions methods. + * Useful for navigation assertion methods like ( column(...) , row(...) ). + * + * @author Julien Roy + */ +class ProxifyPositionResult implements MethodInterceptor { + private final SoftProxies proxies; + + ProxifyPositionResult(SoftProxies proxies) { + this.proxies = proxies; + } + + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + Object result = proxy.invokeSuper(obj, args); + if (isProxified(result.getClass()) || actual(result) == null) { + return result; + } + return this.proxies.create(result.getClass(), actualClass(result), actual(result)); + } + + private static Class[] actualClass(Object result) { + + if (result instanceof AbstractColumnAssert) { + return Arrays.array( + unProxy(((AbstractColumnAssert) result).origin.getClass()), + Column.class + ); + } else if (result instanceof AbstractRowAssert) { + return Arrays.array( + unProxy(((AbstractRowAssert) result).origin.getClass()), + Row.class + ); + } else if (result instanceof AbstractValueAssert) { + return Arrays.array( + unProxy(((AbstractValueAssert) result).origin.getClass()), + Value.class + ); + } else if (result instanceof ChangeAssert) { + return Arrays.array( + unProxy(((ChangeAssert) result).origin.getClass()), + Change.class + ); + } else if (result instanceof ChangeColumnAssert) { + return Arrays.array( + unProxy(((ChangeColumnAssert) result).origin.getClass()), + String.class, + Value.class, + Value.class + ); + } else if (result instanceof ObjectArrayAssert) { + return Arrays.array(Array.newInstance(Object.class, 0).getClass()); + } else { + Type actualType = ((ParameterizedType) result.getClass().getGenericSuperclass()).getActualTypeArguments()[1]; + Class type = actualType instanceof ParameterizedType ? + (Class) ((ParameterizedType) actualType).getRawType() : + (Class) actualType; + return Arrays.array(type); + } + } + + private static Object[] actual(Object result) { + if (result instanceof AbstractColumnAssert) { + return Arrays.array( + ((AbstractColumnAssert) result).origin, + ((AbstractColumnAssert) result).column + ); + } else if (result instanceof AbstractRowAssert) { + return Arrays.array( + ((AbstractRowAssert) result).origin, + ((AbstractRowAssert) result).row + ); + } else if (result instanceof AbstractValueAssert) { + return Arrays.array( + ((AbstractValueAssert) result).origin, + ((AbstractValueAssert) result).value + ); + } else if (result instanceof ChangeAssert) { + return Arrays.array( + ((ChangeAssert) result).origin, + ((ChangeAssert) result).change + ); + } else if (result instanceof ChangeColumnAssert) { + return Arrays.array( + ((ChangeColumnAssert) result).origin, + ((ChangeColumnAssert) result).columnName, + ((ChangeColumnAssert) result).valueAtStartPoint, + ((ChangeColumnAssert) result).valueAtEndPoint + ); + } else { + return null; + } + } +} diff --git a/src/main/java/org/assertj/db/api/SoftAssertions.java b/src/main/java/org/assertj/db/api/SoftAssertions.java new file mode 100644 index 00000000..33be228f --- /dev/null +++ b/src/main/java/org/assertj/db/api/SoftAssertions.java @@ -0,0 +1,71 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2012-2016 the original author or authors. + */ +package org.assertj.db.api; + +import org.assertj.core.api.SoftAssertionError; +import org.assertj.core.groups.Properties; +import org.assertj.db.type.Changes; +import org.assertj.db.type.Request; +import org.assertj.db.type.Table; + +import java.util.List; + +/** + * Implementation of AssertJ SoftAssertions for {@link Table}, {@link Request} and {@link Changes}. + * + * This implementation works like AssertJ SoftAssertions implementation by providing you with + * proxies of the AssertJ-DB assertion objects. + * + * For more details see AssertJ implementation : {@link org.assertj.core.api.SoftAssertions} + * + * @author Julien Roy + */ +public final class SoftAssertions extends AbstractSoftAssertions { + + /** + * Creates a new instance of {@link TableAssert}. + * + * @param table The table to assert on. + * @return The created assertion object. + */ + public TableAssert assertThat(Table table) { + return proxy(TableAssert.class, Table.class, table); + } + + /** + * Creates a new instance of {@link RequestAssert}. + * + * @param request The request to assert on. + * @return The created assertion object. + */ + public RequestAssert assertThat(Request request) { + return proxy(RequestAssert.class, Request.class, request); + } + + /** + * Creates a new instance of {@link ChangesAssert}. + * + * @param changes The changes to assert on. + * @return The created assertion object. + */ + public ChangesAssert assertThat(Changes changes) { + return proxy(ChangesAssert.class, Changes.class, changes); + } + + public void assertAll() { + List errors = this.errorsCollected(); + if (!errors.isEmpty()) { + throw new SoftAssertionError(Properties.extractProperty("message", String.class).from(errors)); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/assertj/db/api/SoftProxies.java b/src/main/java/org/assertj/db/api/SoftProxies.java new file mode 100644 index 00000000..a25279f7 --- /dev/null +++ b/src/main/java/org/assertj/db/api/SoftProxies.java @@ -0,0 +1,81 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2012-2016 the original author or authors. + */ +package org.assertj.db.api; + +import org.assertj.core.api.ErrorCollector; +import org.assertj.core.internal.cglib.proxy.Callback; +import org.assertj.core.internal.cglib.proxy.CallbackFilter; +import org.assertj.core.internal.cglib.proxy.Enhancer; +import org.assertj.core.util.Arrays; + +import java.lang.reflect.Method; +import java.util.List; + +/** + * Proxy implementation utilities. + * + * @author Julien Roy + */ +class SoftProxies { + private final ErrorCollector collector = new ErrorCollector(); + + SoftProxies() { + } + + void collectError(Throwable error) { + this.collector.addError(error); + } + + List errorsCollected() { + return this.collector.errors(); + } + + @SuppressWarnings("unchecked") + V create(Class assertClass, Class actualClass, T actual) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(assertClass); + enhancer.setCallbackFilter(SoftProxies.CollectErrorsOrCreateExtractedProxy.FILTER); + enhancer.setCallbacks(new Callback[] { this.collector, new ProxifyPositionResult(this) }); + return (V) enhancer.create((Class[]) Arrays.array(new Class[] { actualClass }), Arrays.array(new Object[] { actual })); + } + + @SuppressWarnings("unchecked") + V create(Class assertClass, Class[] paramClass, Object[] params) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(assertClass); + enhancer.setCallbackFilter(SoftProxies.CollectErrorsOrCreateExtractedProxy.FILTER); + enhancer.setCallbacks(new Callback[] { this.collector, new ProxifyPositionResult(this) }); + return (V) enhancer.create(paramClass, params); + } + + public boolean wasSuccess() { + return this.collector.wasSuccess(); + } + + private enum CollectErrorsOrCreateExtractedProxy implements CallbackFilter { + FILTER; + + public int accept(Method method) { + return this.isPositionMethod(method) ? 1 : 0; + } + + private boolean isPositionMethod(Method method) { + String methodName = method.getName(); + return + java.util.Arrays.asList("change", "column", "row", "value").contains(methodName) || + methodName.startsWith("changeOf") || + methodName.startsWith("rowAt") || + methodName.startsWith("of"); + } + } +} diff --git a/src/main/java/org/assertj/db/api/assertions/impl/AssertionsOnValueCondition.java b/src/main/java/org/assertj/db/api/assertions/impl/AssertionsOnValueCondition.java index 7264d4ea..c37c6b8d 100644 --- a/src/main/java/org/assertj/db/api/assertions/impl/AssertionsOnValueCondition.java +++ b/src/main/java/org/assertj/db/api/assertions/impl/AssertionsOnValueCondition.java @@ -48,6 +48,7 @@ private AssertionsOnValueCondition() { * @return {@code this} assertion object. * @throws AssertionError If the value is not equal to the number in parameter. */ + @SuppressWarnings("unchecked") public static > A is(A assertion, WritableAssertionInfo info, Value value, Condition condition) { conditions.assertIs(info, value.getValue(), (Condition) condition); return assertion; @@ -64,6 +65,7 @@ public static > A is(A assertion, WritableAssertionI * @return {@code this} assertion object. * @throws AssertionError If the value is not equal to the number in parameter. */ + @SuppressWarnings("unchecked") public static > A isNot(A assertion, WritableAssertionInfo info, Value value, Condition condition) { conditions.assertIsNot(info, value.getValue(), (Condition) condition); return assertion; diff --git a/src/main/java/org/assertj/db/navigation/Position.java b/src/main/java/org/assertj/db/navigation/Position.java index 6eeea897..cf87cebe 100644 --- a/src/main/java/org/assertj/db/navigation/Position.java +++ b/src/main/java/org/assertj/db/navigation/Position.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.Map; +import static org.assertj.db.util.Proxies.unProxy; + /** * Position during navigation. * @@ -99,6 +101,7 @@ public N getInstance(List elementsList) { * @param index Index of the element on which is the instance of element of navigation. * @return The instance of element of navigation. */ + public N getInstance(List elementsList, int index) { if (elementsMap.containsKey(index)) { N rowAssert = elementsMap.get(index); @@ -108,18 +111,21 @@ public N getInstance(List elementsList, int index) { D element = getDbElement(elementsList, index); try { - Constructor constructor = elementClass.getDeclaredConstructor(myself.getClass(), element.getClass()); + + Class clazz = unProxy(myself.getClass()); + Constructor constructor = elementClass.getDeclaredConstructor(clazz, element.getClass()); N instance = constructor.newInstance(myself, element); elementsMap.put(index, instance); instance.as(getDescription(index)); return instance; } catch (Exception e) { throw new AssertJDBException(String.format("There is an exception '" + e.getMessage() - + "'%n\t in the instantiation of the element " + elementClass.getName() + "%n\t on " - + element.getClass() - + " with " + myself.getClass() + ".%n " - + "It is normally impossible.%n That means there is a big mistake in the development of AssertJDB.%n " - + "Please write an issue for that if you meet this problem.")); + + "'%n\t in the instantiation of the element " + elementClass.getName() + + "%n\t on " + + element.getClass() + + " with " + myself.getClass() + ".%n " + + "It is normally impossible.%n That means there is a big mistake in the development of AssertJDB.%n " + + "Please write an issue for that if you meet this problem.")); } } diff --git a/src/main/java/org/assertj/db/navigation/PositionWithChanges.java b/src/main/java/org/assertj/db/navigation/PositionWithChanges.java index 2f01bbdc..7d501451 100644 --- a/src/main/java/org/assertj/db/navigation/PositionWithChanges.java +++ b/src/main/java/org/assertj/db/navigation/PositionWithChanges.java @@ -26,6 +26,8 @@ import java.util.List; import java.util.Map; +import static org.assertj.db.util.Proxies.unProxy; + /** * Position during navigation. * @@ -130,14 +132,16 @@ public E getChangesInstance(Changes changes, ChangeType changeType, String table } try { - Constructor constructor = actualElementClass.getDeclaredConstructor(myself.getClass(), Changes.class); + Class clazz = Class.forName(myself.getClass().getName().replaceAll("\\$\\$.*", "")); + Constructor constructor = actualElementClass.getDeclaredConstructor(clazz, Changes.class); instance = constructor.newInstance(myself, nextChanges); instance.as(getChangesDescription(changeType, tableName)); setInCache(changeType, tableName, instance); return instance; } catch (Exception e) { throw new AssertJDBException(String.format("There is an exception '" + e.getMessage() - + "'%n\t in the instantiation of the element " + actualElementClass.getName() + "%n\t on " + + "'%n\t in the instantiation of the element " + actualElementClass.getName() + + "%n\t on " + Changes.class + " with " + myself.getClass() + ".%n " + "It is normally impossible.%n That means there is a big mistake in the development of AssertJDB.%n " @@ -182,7 +186,7 @@ private Change getChange(Changes changes, int index, ChangeType changeType, Stri * @return The change assert implementation. */ public N getChangeInstance(Changes changes, ChangeType changeType, String tableName) { - return getChangeInstance(changes, changeType,tableName, getIndexNextChange(changeType, tableName)); + return getChangeInstance(changes, changeType, tableName, getIndexNextChange(changeType, tableName)); } /** @@ -202,9 +206,9 @@ public N getChangeInstance(Changes changes, ChangeType changeType, String tableN return instance; } - try { - Constructor constructor = nextElementClass.getDeclaredConstructor(myself.getClass(), Change.class); + Class clazz = unProxy(myself.getClass()); + Constructor constructor = nextElementClass.getDeclaredConstructor(clazz, Change.class); instance = constructor.newInstance(myself, change); instance.as(getChangeDescription(changes, change, index, changeType, tableName)); changeMap.put(change, instance); @@ -212,7 +216,8 @@ public N getChangeInstance(Changes changes, ChangeType changeType, String tableN return instance; } catch (Exception e) { throw new AssertJDBException(String.format("There is an exception '" + e.getMessage() - + "'%n\t in the instantiation of the element " + nextElementClass.getName() + "%n\t on " + + "'%n\t in the instantiation of the element " + nextElementClass.getName() + + "%n\t on " + Change.class + " with " + myself.getClass() + ".%n " + "It is normally impossible.%n That means there is a big mistake in the development of AssertJDB.%n " @@ -251,7 +256,7 @@ public N getChangeInstanceWithPK(Changes changes, String tableName, Object... pk index++; } throw new AssertJDBException("No change found for table " + tableName + " and primary keys " + Arrays - .asList(pksValues)); + .asList(pksValues)); } /** @@ -306,5 +311,5 @@ private void setIndexNextChange(ChangeType changeType, String tableName, int ind * @return The description */ protected abstract String getChangeDescription(Changes changes, Change change, int index, - ChangeType changeType, String tableName); + ChangeType changeType, String tableName); } diff --git a/src/main/java/org/assertj/db/navigation/PositionWithColumnsChange.java b/src/main/java/org/assertj/db/navigation/PositionWithColumnsChange.java index b7a2e6da..dd68ec05 100644 --- a/src/main/java/org/assertj/db/navigation/PositionWithColumnsChange.java +++ b/src/main/java/org/assertj/db/navigation/PositionWithColumnsChange.java @@ -27,6 +27,8 @@ import java.util.List; import java.util.Map; +import static org.assertj.db.util.Proxies.unProxy; + /** * Position during navigation. * @@ -107,19 +109,18 @@ public N getChangeColumnInstance(Change change, int index) { if (rowAtStartPoint != null) { List valuesAtStartPoint = rowAtStartPoint.getValuesList(); valueAtStartPoint = valuesAtStartPoint.get(index); - } - else { + } else { valueAtStartPoint = Value.getNullValue(columnName, change.getColumnLetterCase()); } if (rowAtEndPoint != null) { List valuesAtEndPoint = rowAtEndPoint.getValuesList(); valueAtEndPoint = valuesAtEndPoint.get(index); - } - else { + } else { valueAtEndPoint = Value.getNullValue(columnName, change.getColumnLetterCase()); } try { - Constructor constructor = elementClass.getDeclaredConstructor(myself.getClass(), String.class, Value.class, Value.class); + Class clazz = unProxy(myself.getClass()); + Constructor constructor = elementClass.getDeclaredConstructor(clazz, String.class, Value.class, Value.class); N instance = constructor.newInstance(myself, columnName, valueAtStartPoint, valueAtEndPoint); elementsMap.put(index, instance); nextIndex = index + 1; @@ -218,8 +219,9 @@ public N getModifiedChangeColumnInstance(Change change, String columnName, CaseC return getChangeColumnInstance(change, indexModified); } } - throw new AssertJDBException(String.format("Column <%s> does not exist among the modified columns%nin <%s>%nwith comparison %s", - columnName, modifiedColumnsNameList, comparison.getComparisonName())); + throw new AssertJDBException( + String.format("Column <%s> does not exist among the modified columns%nin <%s>%nwith comparison %s", + columnName, modifiedColumnsNameList, comparison.getComparisonName())); } /** diff --git a/src/main/java/org/assertj/db/navigation/PositionWithPoints.java b/src/main/java/org/assertj/db/navigation/PositionWithPoints.java index 76739f5f..5f199a78 100644 --- a/src/main/java/org/assertj/db/navigation/PositionWithPoints.java +++ b/src/main/java/org/assertj/db/navigation/PositionWithPoints.java @@ -18,6 +18,8 @@ import java.lang.reflect.Constructor; +import static org.assertj.db.util.Proxies.unProxy; + /** * Position with point (start point and end point) during navigation. * @@ -79,7 +81,6 @@ public PositionWithPoints(E myself, Class elementClass, Class pointClass, this.atEndPoint = atEndPoint; } - /** * Gets an instance of element of navigation at start point. * If this instance is already instanced, the method returns it from the cache. @@ -116,12 +117,14 @@ public N getInstanceAtEndPoint() { */ protected N getInstance(D element) { try { - Constructor constructor = elementClass.getDeclaredConstructor(myself.getClass(), pointClass); + Class clazz = unProxy(myself.getClass()); + Constructor constructor = elementClass.getDeclaredConstructor(clazz, pointClass); N instance = constructor.newInstance(myself, element); return instance; } catch (Exception e) { throw new AssertJDBException(String.format("There is an exception '" + e.getMessage() - + "'%n\t in the instantiation of the element " + elementClass.getName() + "%n\t on " + + "'%n\t in the instantiation of the element " + elementClass.getName() + + "%n\t on " + pointClass + " with " + myself.getClass() + ".%n " + "It is normally impossible.%n That means there is a big mistake in the development of AssertJDB.%n " diff --git a/src/main/java/org/assertj/db/util/Proxies.java b/src/main/java/org/assertj/db/util/Proxies.java new file mode 100644 index 00000000..d6afc0b8 --- /dev/null +++ b/src/main/java/org/assertj/db/util/Proxies.java @@ -0,0 +1,46 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2012-2016 the original author or authors. + */ +package org.assertj.db.util; + +import org.assertj.core.internal.cglib.proxy.Enhancer; + +/** + * Utilities for manage proxies. + * + * @author Julien Roy + */ +public class Proxies { + + /** + * Check if class is proxified. + * + * @param clazz Class to check + * @return True if class is proxified by CGLIB + */ + public static boolean isProxified(Class clazz) { + return Enhancer.isEnhanced(clazz); + } + + /** + * Return base of proxified class if it is proxified otherwise return class. + * @param clazz Clazz to evaluate + * @return Class based of proxified + */ + public static Class unProxy(Class clazz) { + if (isProxified(clazz)) { + return clazz.getSuperclass(); + } + return clazz; + } + +} diff --git a/src/test/java/org/assertj/db/api/SoftAssertions_Test.java b/src/test/java/org/assertj/db/api/SoftAssertions_Test.java new file mode 100644 index 00000000..59cc7337 --- /dev/null +++ b/src/test/java/org/assertj/db/api/SoftAssertions_Test.java @@ -0,0 +1,113 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2012-2016 the original author or authors. + */ +package org.assertj.db.api; + +import org.assertj.core.api.SoftAssertionError; +import org.assertj.core.api.ThrowableAssert; +import org.assertj.db.common.AbstractTest; +import org.assertj.db.common.NeedReload; +import org.assertj.db.type.Changes; +import org.assertj.db.type.Request; +import org.assertj.db.type.Table; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * Test on the utility class {@code SoftAssertions}. + * + * @author Julien Roy + * + */ +public class SoftAssertions_Test extends AbstractTest { + + /** + * This method tests the {@code hasValues} assertion method. + */ + @Test + @NeedReload + public void test_soft_assert_table() { + Table table = new Table(source, "test"); + final SoftAssertions softly = new SoftAssertions(); + softly.assertThat(table).as("Show be Zero").column("var1").value().isEqualTo(0); + softly.assertThat(table).column("var2").value().isFalse(); + softly.assertThat(table).row(0).column("var2").value().isFalse(); + softly.assertThat(table).row().value("var2").isFalse(); + softly.assertThat(table).hasNumberOfRows(0); + softly.assertThat(table).hasNumberOfColumns(0); + softly.assertThat(table) + .row(0).column("var2").value().isFalse() + .returnToColumn() + .column("var1").value().isEqualTo(0); + + assertThat(softly.errorsCollected()).hasSize(8); + + assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + @Override public void call() { + softly.assertAll(); + } + }).isInstanceOf(SoftAssertionError.class); + } + + /** + * This method tests the {@code hasValues} assertion method. + */ + @Test + @NeedReload + public void test_soft_assert_request() { + Request request = new Request(source, "select * from test"); + final SoftAssertions softly = new SoftAssertions(); + softly.assertThat(request).column("var1").value(0).isEqualTo(0); + softly.assertThat(request).column("var2").value(0).isFalse(); + softly.assertThat(request).row(0).column("var2").value().isFalse(); + softly.assertThat(request).row().value("var2").isFalse(); + softly.assertThat(request).hasNumberOfRows(0); + softly.assertThat(request).hasNumberOfColumns(0); + softly.assertThat(request) + .row(0).column("var2").value().isFalse() + .returnToColumn() + .column("var1").value().isEqualTo(0); + + assertThat(softly.errorsCollected()).hasSize(8); + + assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + @Override public void call() { + softly.assertAll(); + } + }).isInstanceOf(SoftAssertionError.class); + } + + /** + * This method tests the {@code hasValues} assertion method. + */ + @Test + @NeedReload + public void test_soft_assert_changes() { + Changes changes = new Changes(source); + changes.setStartPointNow(); + update("update test set var14 = 1 where var1 = 1"); + changes.setEndPointNow(); + + final SoftAssertions softly = new SoftAssertions(); + softly.assertThat(changes).change().column("var1").hasValues(0); + softly.assertThat(changes).change().rowAtStartPoint().changeOfModification().column("var1").hasValues(0); + assertThat(softly.errorsCollected()).hasSize(2); + + assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + @Override public void call() { + softly.assertAll(); + } + }).isInstanceOf(SoftAssertionError.class); + } +} diff --git a/src/test/java/org/assertj/db/util/Proxies_Test.java b/src/test/java/org/assertj/db/util/Proxies_Test.java new file mode 100644 index 00000000..059e2ca4 --- /dev/null +++ b/src/test/java/org/assertj/db/util/Proxies_Test.java @@ -0,0 +1,65 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * Copyright 2012-2016 the original author or authors. + */ +package org.assertj.db.util; + +import org.assertj.core.internal.cglib.proxy.Enhancer; +import org.assertj.core.internal.cglib.proxy.NoOp; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test for Proxies utility class. + * + * @author Julien Roy + */ +public class Proxies_Test { + + /** + * Test the {@code isProxified} method with not enhanced class. + */ + @Test + public void test_is_proxy_with_classic_class() { + assertThat(Proxies.isProxified(String.class)).isFalse(); + } + + /** + * Test the {@code isProxified} method with enhanced class. + */ + @Test + public void test_is_proxy_with_enhanced_class() { + Object enhancedClass = Enhancer.create(ClassForProxiesTest.class, NoOp.INSTANCE); + assertThat(Proxies.isProxified(enhancedClass.getClass())).isTrue(); + } + + /** + * Test the {@code unProxy} method with not enhanced class. + */ + @Test + public void test_unproxy_with_classic_class() { + assertThat(Proxies.unProxy(String.class)).isEqualTo(String.class); + } + + /** + * Test the {@code unProxy} method with enhanced class. + */ + @Test + public void test_unproxy_with_enhanced_class() { + Object enhancedClass = Enhancer.create(ClassForProxiesTest.class, NoOp.INSTANCE); + assertThat(Proxies.unProxy(enhancedClass.getClass())).isEqualTo(ClassForProxiesTest.class); + } + + public static class ClassForProxiesTest { + } + +} \ No newline at end of file