I came across an interesting issue with the Hamcrest asserts today. I have a method that returns a list of domain objects, as shown here:

 List<Stakeholder> stakeholders = stakeholderManager.findByName("Telecom"); 

This is a good example of how ]]>

 @Test public void should_find_embedded_search_term_at_start() { List<Stakeholder> stakeholders = stakeholderManager.findByName("Health"); assertThat(stakeholders, hasItem(hasProperty("name",is("Health Associates")))); } 

This Hamcrest assert checks that the list contains at least one Stakeholder object whose name is "Health Associates". This is clearly much nicer than having to iterate through the result list and test each Stakeholder object individually.

Unfortunatly, this doesn't work: you get a compilation error along the following lines:

 The method assertThat(T, Matcher) in the type MatcherAssert is not applicable for the arguments (List<Stakeholder>, Matcher>) 

Indeed, Hamcrest seems to be having trouble with the idea that a List of Stakeholders is also a List of Objects.

So can't we just cast the result (a List<Stakeholder> object) to a List<Object>? The short answer is no. For type-safety reasons that are well-documented elsewhere, you can't cast a List<Stakeholder> to a List<Object>. If you could do this, you could add objects that weren't Stakeholders to the list. However, you can find a work-around fairly easily. But this is where the details get rather interesting. For example, the following seems to compile in Eclipse, but nowhere else:

 List stakeholders = stakeholderManager.findByName("Health"); assertThat(stakeholders, hasItem(hasProperty("name",is("Health Associates")))); 

Outside Eclipse, this will fail with an error along the following lines:

 StakeholderManagerTest.java:[62,8] cannot find symbol symbol : method assertThat(java.util.List,org.hamcrest.Matcher>) 

My friend Eduard Letifovpointed out the following solution, which will work both within Eclipse and using a normal JDK:

 List stakeholders = stakeholderManager.findByName("Health"); List<Object> listOfStakeholders = stakeholderManager.findByName("Health"); assertThat(listOfStakeholders, hasItem(hasProperty("name",is("Health Associates")))); 

Which you can simplify to the following:

 List stakeholders = stakeholderManager.findByName("Health"); assertThat((List<Object>) stakeholders, hasItem(hasProperty("name",is("Health Associates")))); 

That's right, there are two casts here: one from List<Stakeholder> to List, and a second from List to List<Object>. There's sure to be a more elegant way, but it probably involves modifying the signature of the Hamcrest methods. So this will do for now.

Until next time...