1

I am doing an mvc test in my program that the getRecipes() method is supposed to return a list of recipes. Also, the Recipe class has not overridden the equals method and the hashCode.

As it is known in the RecipeService class, a new HashSet is returned every time, but recipes which is in it is the same because its repository is the same. Therefore, we should expect to receive a different HashSet but the same recipe with each call to the getRecipes method, so when calling equals on the hash sets, it should return true because they have the same content, but surprisingly When runnig, we see that these two hash sets have different recipes!

@SpringBootTest
class RecipeControllerTest {
    @Mock
    private Model model;
    @Autowired
    private RecipeService recipeService;
    @Autowired
    private RecipeController recipeController;

    @Test
    public void testMVC() {
        try {
            MockMvc mockMvc = MockMvcBuilders.standaloneSetup(recipeController).build();
            mockMvc.perform(MockMvcRequestBuilders.get("/"))
                    .andExpect(status().isOk())
                    .andExpect(model().attribute("recipes", recipeService.getRecipes()))
                    .andExpect(view().name("index"));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

RecipeService class:

public class RecipeService {
    private final RecipeRepository recipeRepository;

public RecipeService(RecipeRepository recipeRepository) {
    this.recipeRepository = recipeRepository;
}

 public Set<Recipe> getRecipes(){
        log.debug("debugging message inside of "+getClass().getSimpleName());
        Set<Recipe> recipes=new HashSet<>();
         recipeRepository.findAll().forEach(recipes::add);
         return recipes;
    }
}

error:

java.lang.AssertionError: Model attribute 'recipes' expected:<[com.arbabsoft.recipe.model.Recipe@4619854a]> but was:<[com.arbabsoft.recipe.model.Recipe@6eff05e7]>
Expected :[com.arbabsoft.recipe.model.Recipe@4619854a]
Actual   :[com.arbabsoft.recipe.model.Recipe@6eff05e7]

But when I apply the following changes to the RecipeControllerTest class, the test passes.

@Mock
private RecipeService recipeService;
@InjectMocks
private RecipeController recipeController;

What is the reason for this? Did JUnit, Mockito and spring MVC test conflict?

fast
  • 51
  • 4
  • 2
    There is no assert so what you see and state doesn't really make sense. But they aren't the same I I suspect it is due to you not implementing a proper `equals` and `hashCode` in your `Recipe`. – M. Deinum Aug 17 '22 at 14:24
  • @M.Deinum equals is supposed to compare memory addresses. hashcode also returns the memory address by default. It really shouldn't be a problem! – fast Aug 17 '22 at 14:29
  • 1
    And if you have a hashset with 2 different object instances from the database they aren't equal... Because they are 2 different instances of the same row. Hence a proper equals and hashcode is important. Even more important when you use JPA (see https://vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/) as well. – M. Deinum Aug 17 '22 at 14:44
  • 1
    The assert is in the method `.andExpect(model().attribute("recipes", recipeService.getRecipes()))` anyway are you sure that two different call to the repositories produces the same object? Make a test calling twice the recipeService.getRecipes() and compare if the memory address are the same for the recipe. If you use mock the service will always return the object you give it – Pp88 Aug 17 '22 at 15:27
  • @Pp88 I checked that the repository is the same for both – fast Aug 17 '22 at 17:49
  • 1
    I’m not talking about the repository bean but the recipe object returned by two different calls to findAll, that in my opinion should be different, so as suggested you have to override equals – Pp88 Aug 17 '22 at 17:57

0 Answers0