assertj / assertj Goto Github PK
View Code? Open in Web Editor NEWAssertJ is a library providing easy to use rich typed assertions
Home Page: https://assertj.github.io/doc/
License: Apache License 2.0
AssertJ is a library providing easy to use rich typed assertions
Home Page: https://assertj.github.io/doc/
License: Apache License 2.0
Add two new assertions to ThrowableAssert
:
hasCause(Throwable e);
hasRootCause(Throwable e);
Also, maybe (is this too specific?) add instanceOf
checks for cause:
hasCauseOfClass(Class<? extends Throwable> eClass);
hasRootCauseOfClass(Class<? extends Throwable> eClass);
First rename assertion to containsKeys
It would allow to write :
assertThat(elvesRingBearers).containsKeys(nenya, narya, vilya);
instead of
assertThat(elvesRingBearers).containsKey(nenya).containsKey(narya).containsKey(vilya);
To avoid doing this:
String json = getPolicyInfoFromRemoteSystem();
assertThat(json).contains("{")
.contains("}")
.contains("coverages");
The contains()
method on StringAssert
could take a varargs of String
, e.g.:
assertThat(json).contains("{", "}", "coverages", "vehicle");
Most (if not all) of the class types for which assertions are provided for have a parent type of Object
. In practice, the types for which custom assertions will be written will likely have a much more complex hierarchy of classes. How should we deal with this case?
An example, for clarity:
class Human {
public String name;
}
class Employee extends Human {
public String jobTitle;
}
class HumanAssert extends AbstractAssert<HumanAssert, Human> {
public HumanAssert(Human actual) {
super(actual, HumanAssert.class);
}
public HumanAssert hasName(String name) {
isNotNull();
assertThat(actual.name).isEqualTo(name);
return this;
}
}
Now, how to craft EmployeeAssert
? Thus far I've been doing the following:
class EmployeeAssert extends HumanAssert {
private final Employee actual;
public EmployeeAssert(Employee actual) {
super(actual);
this.actual = actual;
}
public EmployeeAssert hasJobTitle(String jobTitle) {
isNotNull();
assertThat(actual.jobTitle).isEqualTo(jobTitle);
return this;
}
}
This mostly works and allows chained assertions like:
assertThat(employee).hasJobTitle("CEO").hasName("John Smith");
but does not allow:
assertThat(employee).hasName("John Smith").hasJobTitle("CEO");
since the return type of hasName
is HumanAssert
rather than EmployeeAssert
.
If you extrapolate this case to hierarchies that are three or four classes deep you can quickly see it becomes a mess in forcing your assertions to be written in descending order of the hierarchy if you want to continue chaining.
This can be solved with this (thnaks to by Jake Wharton) :
class AbstractHumanAssert<S extends AbstractHumanAssert<S, A>, A extends Human> extends AbstractAssert<S, A> {
public AbstractHumanAssert(A actual, Class<S> selfType) {
super(actual, selfType);
}
public S hasName(String name) {
isNotNull();
Assertions.assertThat(actual.name).isEqualTo(name);
return myself;
}
}
class HumanAssert extends AbstractHumanAssert<HumanAssert, Human> {
public HumanAssert(Human actual) {
super(actual, HumanAssert.class);
}
}
class AbstractEmployeeAssert<S extends AbstractEmployeeAssert<S, A>, A extends Employee> extends
AbstractHumanAssert<S, A> {
public AbstractEmployeeAssert(A actual, Class<S> selfType) {
super(actual, selfType);
}
public S hasJobTitle(String title) {
isNotNull();
Assertions.assertThat(actual.jobTitle).isEqualTo(title);
return myself;
}
}
class EmployeeAssert extends AbstractEmployeeAssert<EmployeeAssert, Employee> {
public EmployeeAssert(Employee actual) {
super(actual, EmployeeAssert.class);
}
}
class AbstractUnitedStatesEmployeeAssert<S extends AbstractUnitedStatesEmployeeAssert<S, A>, A extends UnitedStatesEmployee>
extends AbstractEmployeeAssert<S, A> {
public AbstractUnitedStatesEmployeeAssert(A actual, Class<S> selfType) {
super(actual, selfType);
}
public S isInState(String state) {
isNotNull();
Assertions.assertThat(actual.state).isEqualTo(state);
return myself;
}
}
class UnitedStatesEmployeeAssert
extends AbstractUnitedStatesEmployeeAssert<UnitedStatesEmployeeAssert, UnitedStatesEmployee> {
public UnitedStatesEmployeeAssert(UnitedStatesEmployee actual) {
super(actual, UnitedStatesEmployeeAssert.class);
}
}
Certainly not ideal, but it works for all permutations listed in the previous comment.
I thought you might be interested in introducing a new feature similar to AbstractIterableAssert.extracting()
, which was not based on String-reflection for a property. Thew new syntax in usage would look sort of like:
assertThat(fellowshipOfTheRing).evaluating(call(TolkienCharacter.class).getName()).contains("Gandalf", "Frodo", "Legolas");
By avoiding String-based reflection, you get two features. First IDE-provided refactorings are more safe (especially rename-method or rename-field). Secondly, you get increased type-safety on the evaluated return type (extracting
currently returns ListAssert<Object>
rather than ListAssert<T>
).
This feature could be implemented using the same techniques I have used to create my OSS project: Funcito (https://code.google.com/p/funcito/). It could have most of the same features as Funcito, including method-chaining. It would also have the same limitations (https://code.google.com/p/funcito/wiki/FAQ#What_are_the_limitations_of_Funcito? ).
Of course when Java 8 is complete, there would be an easier way to implement this feature than the Funcito-style route, but this style would still be valuable for those who remain in Java 5-7.
I may be available to help, or at least I would be available for consultation.
Try something like:
assertThat(map).valueForKey("key1").isEqualTo("foo")
.valueForKey("key2").doesNotExist()
as suggested in alexruiz/fest-assert-2.x#117
original issues : alexruiz/fest-assert-2.x#46
I think that ReaderAssert should be implemented. Basically the functionality should have assertion methods to compare to other Reader as well as some textual support.
From my point of view, it will be cool if you could make an assertion if Reader contains some text. The question is how much similarity with StringAssert should be there?
It is a different way of asserting order in collections, example :
List<String> book = list("title", "A Game of Thrones", "author", "George Martin");
assertThat(book).containsInOrder("A Game of Thrones", "George Martin");
Let's say I have an array that looks like this:
String[] array = new String[] { "--option", "a=b", "--option", "c=d" };
I want to assert that the array has "--option"
and "c=d"
in sequence, so I write this:
assertThat( array ).containsSequence( "--option", "c=d" )
The assertion shouldn't fail because the array does contain that sequence. But it does fail because Arrays.assertContainSequence
assumes that the first occurrence of "--option"
marks the start of the sequence.
The following code does not compile because of generics :
List<String> strings0 = new ArrayList<String>();
List<? extends String> strings1 = new ArrayList<String>();
assertThat( strings0 ).isEqualTo( strings0 );
assertThat( strings0 ).isEqualTo( strings1 ); // compile error
assertThat( strings1 ).isEqualTo( strings1 ); // compile error
assertThat( strings1 ).isEqualTo( strings0 ); // compile error
Exact signature :
public S doesNotContainAnyElementsOf(Iterable<? extends T> iterable)
it would be handy to have
int[] myArray = ...
assertThat(myArray).containsExactly(1,4,7);
Some assertions error message are single line which is not very handy in IDE, one must often copy the message in a text editor and reformat it to read it easily.
Let's take the failing assertion below :
Date date = parse("2002-12-18");
assertThat(date).isBefore("2002-12-10");
It leads to an assertion error with the following message in Eclipse :
java.lang.AssertionError: expected:<2002-12-18T00:00:00> to be strictly before:<2002-12-10T00:00:00>
But it would be more readable if it were multiline like this :
java.lang.AssertionError:
expected:
<2002-12-18T00:00:00>
to be strictly before:
<2002-12-10T00:00:00>
Iterables.assertContainsExactly(AssertionInfo info, Iterable<?> actual, Object[] values)
calls checkIsNotNullAndNotEmpty(values) and throws an IllegalArgumentException with message "The array of values to look for should not be empty" EVEN if values AND actual are empty. Expected bahvior is to return successfully.
Hello,
In AbstractAssert class, there is a method named
public S overridingErrorMessage(String newErrorMessage, Object[] args)
This method is calling the String.format(newErrorMessage, args)
even if args is empty and newErrorMessage contains '%' which makes assertion fails (See JUnit stacktrace bellow).
In my case, newErrorMessage is equal to:
"Not save action returned for column " + column.getShortName())
where column.getShortName() is:
Last Shift (%))
Maybe this method should check if args is null/empty and then do not call String.format...
java.util.UnknownFormatConversionException: Conversion = ')'
at java.util.Formatter.checkText(Formatter.java:2547)
at java.util.Formatter.parse(Formatter.java:2533)
at java.util.Formatter.format(Formatter.java:2469)
at java.util.Formatter.format(Formatter.java:2423)
at java.lang.String.format(String.java:2797)
at org.assertj.core.api.AbstractAssert.overridingErrorMessage(AbstractAssert.java:300)
at com.socgen.domino.gui.action.configuration.ConfigurationActionTest.testRTPWarrantDSSave(ConfigurationActionTest.java:150)
at com.socgen.domino.gui.action.configuration.ConfigurationActionTest.testSaveRTPWarrantDSActions(ConfigurationActionTest.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
I noticed that org.assertj.core.internal.Strings.assertDoesNotMatch()
allows actual
to be null
- this seems to be inconsistent with other asserts. WDYT?
There are two pages describing how to contribute:
I think the first one can be deleted not to confuse users :) Link to the second one, as you brobably know, is shown when you try to open pull request so it should be left as is.
Proposal :
public TolkienCharacterAssert hasAge(int age) {
// check if the condition to assert is met
if (actual.getAge() != age) {
failWithMessage("Expected character's age to be <%s> but was <%s>", age, actual.getAge());
}
// return the current assertion for method chaining
return this;
where failWithMessage
is defined in AbstractAssert
protected void failWithMessage(String errorMessage, Object... arguments) {
throw Failures.instance().failure(info, new BasicErrorMessageFactory(errorMessage, arguments));
}
failWithMessage
is protected because it is only intended for extending AssertJ, it respects user description and overriden error message if any.
The idea is to support both StringBuilder and StringBuffer in a very natural way, without converting them to String which is less readable.
Internally, the CharSequenceAssert should have exactly the same code as StringAssert, just the conversion from CharSequence to String will be done internally. That means almost no changes in code.
Joes suggested, that we could still have a StringAssert class inheriting from CharSequenceAssert, so that StringAssert is still here and you could have StringBuilder and StringBuffer assertions.
Documentation found at: https://github.com/joel-costigliola/assertj-core/wiki/Using-conditions#verifying-condition-on-collection-elements describes the use of the method set( )
.
But the listed import:
// import static org.assertj.util.Collections.set;
does not exist.
Hi
There is a mix between the test case name and the tested methods in both :
src/test/java/org/assertj/core/internal/throwables/Throwables_assertHasMessageEndingWith_Test.java
src/test/java/org/assertj/core/internal/throwables/Throwables_assertHasMessageContaining_Test.java
Regards
The idea is to be able to extract then check several fields or properties at once, e.g :
assertThat(fellowshipOfTheRing).extracting("race", "name").contains(tuple(HOBBIT, "Frodon"), tuple(HOBBIT, "Frodon"));
Note that extracted values are stored in tuples (Tuple
is a simple structure containing objects) so you must use Tuple
in the chained assertion.
Assertions
provides a handy static method to build tuple, e.g. tuple(HOBBIT, "Frodon")
We want to perform a true chronological comparison and not a field by field comparison.
Let's see that on an example :
Date date = parseDatetime("2003-04-26T13:01:02"); // 0 ms
Date dateMinusOneMs = new Date(date.getTime() - 1);
// This assertion should not fail as dates time difference is only 1ms.
assertThat(date).isInSameSecondWindowAs(dateMinusOneMs);
Also clean isInSameXXXAs javadoc to make clear that they don't perform a true chronological comparison.
For example, let's consider the class :
class Basket {
public String price;
}
we can then write an assertion to check prices like :
assertThat(baskets).extracting("price").containsOnly("12.65", "42.00", "66.60");
this should work if baskets is an array or an iterable.
see alexruiz/fest-assert-2.x#129 for a solution
// succeeds if myNumber == 5 or 10
assertThat(myNumber).isBetween(5, 10);
// fails if myNumber == 5 or 10
assertThat(myNumber).isStrictlyBetween(5, 10);
Let's eat our own dog food !
Just an idea for the time being ... see if it is worth it.
Some ideas :
// special methods
assertThat(Jedi.class).hasSubClass(HumanJedi.class);
assertThat(HumanJedi.class).inheritsFrom(Jedi.class);
// Wrap methods :
assertThat(Jedi.class).containsAnnotation(GreatPower.class, Good.class);
assertThat(Jedi.class).isNotInterface();
assertThat(GreatPower.class).isAnnotation() ;
assertThat(Jedi.class).hasFields("name","sabercolor");
assertThat(Jedi.class).hasDeclaredFields("secretField");
...
To resume, wrap most of is/get methods.
Static mutable state can lead to problems in case of parallel test execution. For example when different tests set different date formats.
It would nice to be able to test that different portions of a string appears in order (whatever is between them). So at each eaten verified "subsequence", the assertion will verify only to the rest of the non verified String.
It could be useful to verify a portion of an XML node for example.
For example, the assertion below would succeed ...
String book = "{ 'title':'A Game of Thrones', 'author':'George Martin'}";
assertThat(book).containsSequence("{", "title", "A Game of Thrones", "}");
... while this one would fail as "author" comes after "A Game of Thrones" :
assertThat(book).containsSequence("{", "author", "A Game of Thrones", "}");
In FEST 1.x, you would write :
assertThat(fellowshipOfTheRing).onProperty("name").contains("Gandalf", "Frodo", "Legolas");
In AssertJ, it becomes :
// static import of assertThat and extractProperty
import static org.assertj.core.api.Assertions.*;
assertThat(extractProperty("name").from(fellowshipOfTheRing)).contains("Gandalf", "Frodo", "Legolas");
But some may like to use code completion after assertThat, so we reintroduce 'onProperty' but this tie it will be named extracting
:
assertThat(fellowshipOfTheRing).extracting("name").contains("Gandalf", "Frodo", "Legolas");
I thought you might be interested in introducing a new feature similar to AbstractIterableAssert.extracting()
The new format in usage would look like:
assertThat(fellowshipOfTheRing).evaluating(call(TolkienCharacter.class).getName()).contains("Gandalf", "Frodo", "Legolas");
The advantage over extracting
is not having to use String-based reflection, which makes automated code refactoring easier to rename methods/fields, etc.
This feature could be implemented using techniques similar to what I use for my project Funcito at http://funcito.googlecode.com for encapsulating proxied method calls as Function-like objects. I could possibly help out with this if you wanted, but I'm not sure how much time I would have to do so. Also, as in Funcito, it could possibly support method-chaining as well. It would have all of the same caveats as Funcito (does not work on final classes/methods, etc., see: https://code.google.com/p/funcito/wiki/FAQ#What_are_the_limitations_of_Funcito? )
Often, testing map entries looks like :
Map<String, String> address = ....
assertThat(address).hasSize(15)
.includes(
MapAssert.entry("zip", "43865"),
MapAssert.entry("lastName", "Frazier"),
MapAssert.entry("state", "IA"),
MapAssert.entry("city", "Culloden")
);
We can simplify this by getting rid of the repeated MapAssert.entry calls:
Map<String, String> address = ....
assertThat(address).hasSize(15)
.containsEntry("zip", "43865")
.containsEntry("lastName", "Frazier")
.containsEntry("state", "IA")
.containsEntry("city", "Culloden");
see alexruiz/fest-assert-2.x#117
Added : do the same thing for the opposite assertion doesNotContainEntry
I think that isWithinXXX
assertions is not a great name (yes it was my idea ...), I come up with a clearer name (I hope), let's see that with an example:
Before:
assertThat(myBirthday).isWithinMinute(27);
Options 1:
assertThat(myBirthday).hasMinuteFieldEqualTo(27);
Options 2:
assertThat(myBirthday).hasMinute(27);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.