Giter Site home page Giter Site logo

assertj / assertj Goto Github PK

View Code? Open in Web Editor NEW
2.6K 2.6K 683.0 43.77 MB

AssertJ is a library providing easy to use rich typed assertions

Home Page: https://assertj.github.io/doc/

License: Apache License 2.0

Java 99.71% Shell 0.21% Groovy 0.02% Kotlin 0.05% CSS 0.01%
assertions assertj hacktoberfest java testing typed-assertions

assertj's Introduction

AssertJ - Fluent Assertions for Java Maven Central Javadocs

CI Cross-Version Binary Compatibility Quality Gate Status

Open in Gitpod

AssertJ provides a rich and intuitive set of strongly-typed assertions to use for unit testing (with JUnit, TestNG or any other test framework).

You can ask questions in stackoverflow (assertj tag) and make suggestions by simply creating an issue.

AssertJ's ambition is to provide a rich and intuitive set of strongly-typed assertions for unit testing.

The idea is that disposal assertions should be specific to the type of the objects we are checking when writing unit tests. If you're checking the value of a String, you use String-specific assertions. Checking the value of a Map? Use Map-specific assertions to easily check the contents of the map.

AssertJ's assertions are super easy to use: just type assertThat(underTest). and use code completion to show you all assertions available.

Assertion missing? Please create an issue to discuss it and even better contribute to the project!

AssertJ is composed of several modules:

You are encouraged to contribute any missing useful assertions.

Please read the contributing section and raise a PR!

assertj's People

Contributors

alexbischof avatar alexruiz avatar ascopes avatar ash2k avatar bjhargrave avatar cgrabmann avatar chriscancompute avatar dependabot-preview[bot] avatar dependabot[bot] avatar ebundy avatar epeee avatar fiery-phoenix avatar filiphr avatar hazendaz avatar jcgay avatar joel-costigliola avatar kriegfrj avatar mariuszs avatar mhaligowski avatar mkordas avatar mwajcht avatar nach-o-man avatar nfrancois avatar olim7t avatar olivierdemeijer avatar pascalschumacher avatar scordio avatar twillouer avatar valery1707 avatar wanghy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

assertj's Issues

allow extracting several fields or properties in iterable or array assertions

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")

extracting() method should be able to extract fields

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.

Add StringAssert.containsSequence

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", "}");

Implement ReaderAssert in a similar way as InputStreamAssert

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?

reintroduce onProperty feature but named it extracting

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");

Improve MapEntry assertions

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

Problem with AbstractAssert.overridingErrorMessage(String newErrorMessage, Object[] args)

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)

Add containsInOrder assertion

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");

MapAssert.containsKey should use varargs params

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);

Add cause assertions to ThrowableAssert

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);

new feature for non-string reflection evaluation, similar to "extracting"

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? )

Make custom assertions easier to write

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.

isEqualTo should not use generics

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

Implement Class assertions

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.

Introduce CharSequenceAssert to support StringBuffer and StringBuilder assertions

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.

Improve assertions chaining for inherited Assert classes

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.

add isInSame<Second/Minute/Hour>WindowAs assertions

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.

new feature for non-string reflection evaluation, similar to "extracting"

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.

Rename Date assertions isWithinXXX to hasXXXFieldEqualTo

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);

Two contribution guides

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.

containsSequence assertion stops after first partial match

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.

Assertions error messages should be multiline for better readability

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>

Mix in test case name and tested methods

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.