I read that it is preferable to use the Set instead List in Hibernate relation.
I created two entities in relation to one to many:
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String name;
@ManyToOne
@JoinColumn(name = "company_id", nullable = false)
private Company company;
}
@Entity
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String name;
@LazyCollection(LazyCollectionOption.TRUE)
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
private Set<Product> products;
}
In relation @OneToMany set collection private Set products;
Then I try to test the return result:
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class CompanyControllerTest {
private static final String API_COMPANY = "/api/company/";
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.build();
}
@Test
public void getById() throws Exception {
int id = 1;
this.mockMvc.perform(get(API_COMPANY + id))
.andExpect(status().isOk())
.andExpect(content().contentType(APPLICATION_JSON_UTF8))
.andExpect(jsonPath("id", is(1)))
.andExpect(jsonPath("$.name", is("Google")))
.andExpect(jsonPath("$.products", hasSize(2)))
.andExpect(jsonPath("$.products[0].id", is(1)))
.andExpect(jsonPath("$.products[0].name", is("search engine")))
.andExpect(jsonPath("$.products[0].company").doesNotExist())
.andExpect(jsonPath("$.products[1].id", is(2)))
.andExpect(jsonPath("$.products[1].name", is("adv.")))
.andExpect(jsonPath("$.products[1].company").doesNotExist());
}
}
But the problem is that the list of products is constantly changing, because I use a Set. And it turns out that the test either passes or fails, since the order of the products changes.
My question is how to test the result when using Set.
You can get all the elements with [*] and give a Matchers.containsInAnyOrder(T...) all the elements that you want to check.
Something like this:
this.mockMvc.perform(get(API_COMPANY + id))
.andExpect(status().isOk())
.andExpect(content().contentType(APPLICATION_JSON_UTF8))
.andExpect(jsonPath("id", is(1)))
.andExpect(jsonPath("$.name", is("Google")))
.andExpect(jsonPath("$.products", hasSize(2)))
.andExpect(jsonPath("$.products[*].id", Matchers.containsInAnyOrder(1, 2)))
.andExpect(jsonPath("$.products[*].name", Matchers.containsInAnyOrder("search engine", "adv.")))
.andExpect(jsonPath("$.products[*].company").doesNotExist());