Repository navigation
Description
Feature summary
I propose the additional of a unwrap method to get the actual value of the current Assert
Example
String objName = assertThat(obj).extracting(MyClass::getName).isNotNull().unwrap()Reasoning
Ideally, in unit tests and with assertJ's fluent api, there should be little need to get the actual value back.
The use of some unwrap method might indicate bad test design, because a test should do only one thing and if you need a nested value for anything other than more assertions, your test does more than one one thing probably.
I assume this is part of the reason why it doesn't exist at the moment. No need/could promote bad practice.
Lately, I've used assertJ a lot for system integration tests on rest api level as well together with other great libraries like awaitility. I often find myself in the situation that I need to verify nested objects and then continue with them.
Compare this case
var order = orderApi.getOrder(orderId);
var troubleTicketRef = assertThat(order)
/* ... order assertions */
.extracting(Order::getPositions)
.asInstanceOf(list(Position.class))
.singleElement()
/* ... position assertions */
.extracting(Position::getReferences)
.asInstanceOf(list(Reference.class))
.filteredOn("type", "troubleTicket")
.singleElement()
/* ... assertions on config reference **/
.unwrap();
var troubleTicket = troubleTicketApi.get(troubleTicketRef.getId());
assertThat(troubleTicket)
/* ... */;At that point I find myself to replicate a lot of the access or assertion logic, because I can't just simply get Y out of the assertion chain.
A workaround is to use satisfy to save the actual value in a reference and retrieve it by side effect, but that is ugly of course.
So for use cases on a higher level than unit tests, I think an unwrap method would be a great addition.
Sorry, if this was asked before. I searched through the repository to find something similar. I would have made a simple PR and let you decide there for this minor addition, but I wanted to understand and respect the project philosophy before I do that.
Team decision: adding actual().
Activity
scordio commentedon May 26, 2024
Could you provide a real-life example you'd like to see improved?
A similar request has been made at #1652 and #3262, but I wonder if yours is 100% a duplicate.
joel-costigliola commentedon May 26, 2024
I want to understand a bit more the problem you are trying to solve @goatfryed.
You are talking about asserting on X and then want to get Y out of X and make further assertions on Y.
I would typically write something like:
Is there something that prevents you to do that ? Maybe there is no
getName()and you would need to use introspection to get it ? I don't think it is that ugly (but that's just my opinion)If I understand you correctly, you would prefer code like:
Note this other alternative:
goatfryed commentedon May 27, 2024
I've updated the description. The initial example was indeed quite abstract.
I find this helpful mostly in combination with deeper nested list properties. Especially in combination with thinks like filteredOn.
It's not difficult to access the nested value for further processing, but it feels redundant to traverse the object structure once to assert and then a second time to continue processing.
My use case is mostly in integration test calling various apis. Here, the object tree tends to get large. It's not even mostly about filtering. Some of my use cases include paths like
order.items[0].product.relations[0].product.places[0].address. So even if the access chain is straightforward, it feels redundant and makes the test harder to read, because the reader needs to understand that i'm accessing the previously asserted element with my call chain.thunderhook commentedon Aug 7, 2024
I think this is the same thing that was proposed/requested in #2098 and #1931 (comment). We also have some parts of our large testing codebase where something like this might be useful.
While this may not be considered to be part of the API, you can use the custom extension mentioned in #1931 (comment) which would be used in your example like this:
You can of course adapt the extension and rename
getActual()tounwrap().joel-costigliola commentedon Aug 8, 2024
We are discussing with the team about exposing actual (likely through an
actual()method rather thanunwrap()), we'll keep you up to date when a decision has been reached.joel-costigliola commentedon Aug 19, 2024
Team decision: adding
actual().Expose actual the object under test
scordio commentedon Sep 9, 2024
Related use case: https://stackoverflow.com/a/78965016/9714611
[-]Add an unwrap method to the API to get actual value[/-][+]Add `actual()` to access the object under test[/+]Expose actual the object under test