Comments (7)
Although it's possible to obtain the previous behavior, similar to how you did it with TypeAwareListAssert
, I believe we should provide better support for such use cases.
However, I wouldn't reintroduce what we've been deprecating as it's less discoverable.
What if we would add an API to configure the assertions for the available navigation methods?
Something like:
assertThat(List.of("a", "b", "c"))
.withElementAssert(StringAssert::new)
// further assertions on the list
.hasSize(3)
// navigation method
.first() // returns StringAssert instead of ObjectAssert<String>
// further String assertions on the element
...
Then, your example would become:
public AbstractListAssert<?, List<? extends String>, String, ? extends AbstractStringAssert<?>> arguments() {
isNotNull();
var arguments = actual.getArguments();
return Assertions.assertThat(arguments)
.withElementAssert(StringAssert::new)
.as("Compiler arguments %s", StringUtils.quotedIterable(arguments));
}
from assertj.
I also heavily use FactoryBasedNavigableListAssert
and love the proposal for withElementAssert
. I actually wanted to open an issue for improving the generics, but then saw this issue about it beeing deprecated. So I'll post here.
Currently FactoryBasedNavigableListAssert
and by extension the deprecated assertThat method requires the ELEMENT_ASSERT
to extend AbstractAssert<ELEMENT_ASSERT, ELEMENT>
. This sounds reasonable at first and works fine for concrete assert classes, but the bound is too tight for generic assert classes such as abstract ones.
Consider the following example:
import java.util.List;
import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.AbstractIntegerAssert;
import org.assertj.core.api.AssertFactory;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.ClassAssert;
import org.assertj.core.api.FactoryBasedNavigableListAssert;
public class Test {
public static void main(String[] args) {
List<Class<?>> actualClasses = List.of(Integer.class);
ClassAssert classAsserter1 = Assertions.assertThat(actualClasses.get(0));
ClassAssert classAsserter2 = Assertions.assertThat(actualClasses, Assertions::assertThat).element(0);
ClassAssert classAsserter3 = assertThat2(actualClasses, Assertions::assertThat).element(0);
List<Integer> actualIntegers = List.of(0);
AbstractIntegerAssert<?> integerAsserter1 = Assertions.assertThat(actualIntegers.get(0));
AbstractIntegerAssert<?> integerAsserter2 =
Assertions.assertThat(actualIntegers, Assertions::assertThat).element(0);
AbstractIntegerAssert<?> integerAsserter3 = assertThat2(actualIntegers, Assertions::assertThat).element(0);
}
public static <ACTUAL extends List<? extends ELEMENT>, ELEMENT, ELEMENT_ASSERT extends AbstractAssert<? extends ELEMENT_ASSERT, ELEMENT>> FactoryBasedNavigableListAssert<?, ACTUAL, ELEMENT, ELEMENT_ASSERT> assertThat2(
List<? extends ELEMENT> actual, AssertFactory<ELEMENT, ELEMENT_ASSERT> assertFactory) {
return null;
}
}
For the List<Class<?>>
everything works fine, because assertThat(Class<?> actual)
returns the non-generic type ClassAssert
, but for integers it does not compile. The reason is that AbstractIntegerAssert<?>
which is the return type of assertThat(Integer actual)
does not satisfy the bound i mentioned above: AbstractAssert<ELEMENT_ASSERT, ELEMENT>
. The bound should really be AbstractAssert<? extends ELEMENT_ASSERT, ELEMENT>
. To prove this change makes it work I added the method assertThat2
in the example. This method doesn't compile because the incorrect upper bound also appears in the declaration of FactoryBasedNavigableListAssert
and its superclasses, but the call to assertThat2 does compile.
from assertj.
Thanks for your feedback, @ascopes!
Please give me a bit of time to get familiar with your use case – I'll get back to you.
from assertj.
This sounds like a very good idea, and would be very helpful! I struggled with getting generics to work consistently for this so any help would be greatly appreciated like this on AssertJ's side to simplify this.
from assertj.
Sounds sensible to me! I'd need to release a new version to change to a new API anyway so there is no rush
from assertj.
Would it be okay if we introduce such a change in 3.27.0?
I'd prefer to have enough time to digest it properly, and the deprecations will only be removed in version 4.
from assertj.
Thanks a lot for your feedback, @Adrodoc55. I'll keep that in mind!
from assertj.
Related Issues (20)
- Add an unwrap method to the API to get actual value HOT 3
- Ambiguous `assertThat` for `Temporal` instance implementing `Comparable` HOT 3
- 3.26 - Ambiguous assertThat with Temporal implementation HOT 1
- Extra variant for doesNotMatch
- Add an annotation Class navigation method
- Recursive Comparison With Ignored Fields Fails On Equal Collections HOT 4
- hasFieldOrPropertyWithValue accepting arrays
- reference to assertThat is ambiguous when asserting a `java.time.Year` HOT 1
- JPMS assertions HOT 2
- Do we have any way to describe the expected value? HOT 1
- Consider `ClassBasedNavigableIterableAssert` and `ClassBasedNavigableListAssert` for deprecation
- Add assertion methods for floating point and integer format of `BigDecimal` HOT 7
- comparingOnlyFields get data of all fields HOT 7
- NPE when usingRecursiveAssertion with field with anonymous Type HOT 1
- AllOf should report which condition failed HOT 2
- usingRecursiveComparison returns false positive when java record has a boolean method with certain naming pattern HOT 2
- IntrospectionError: Unable to find property 'key' in java.util.KeyValueHolder HOT 1
- expose strictTypeChecking via ConfigurationProvider HOT 3
- `inBinary` not exposed for `String` assertions
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from assertj.