'Testing Spring Hateoas Application with RepresentationModelAssembler

I'm trying to test my Spring Hateoas application, more specifically the controllers, using Springs @WebMvcTest. But I'm having problems injecting my custom RepresentationModelAssembler into the test.

First a bit of my setup: I'm using a custom RepresentationModelAssembler to turn my DB-Models into DTOs, which have all necessary links added.

The RepresentationModelAssembler:

@Component
public class BusinessUnitAssembler implements RepresentationModelAssembler<BusinessUnit, BusinessUnitDto> {

    private final Class<BusinessUnitController> controllerClass = BusinessUnitController.class;

    private final BusinessUnitMapper businessUnitMapper;

    public BusinessUnitAssembler(BusinessUnitMapper businessUnitMapper) {
        this.businessUnitMapper = businessUnitMapper;
    }

    @Override
    public BusinessUnitDto toModel(BusinessUnit entity) {
        return businessUnitMapper.businessUnitToDto(entity)
                .add(linkTo(methodOn(controllerClass).findById(entity.getId())).withSelfRel());
    }
}

The BusinessUnitMapper used here is a Mapstruct mapper, which is injected by spring. In my Service I use the BusinessUnitAssembler to turn my DB-Models into DTOs, example Service method:

public Page<BusinessUnitDto> findAll(Pageable pageable) {
    Page<BusinessUnit> pagedResult = businessUnitRepository.findAll(pageable);

    if (pagedResult.hasContent()) {
        return pagedResult.map(businessUnitAssembler::toModel);
    } else {
        return Page.empty();
    }
}

This is how I'm doing the testing currently:

@WebMvcTest(controllers = BusinessUnitController.class)
public class BusinessUnitControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private BusinessUnitService businessUnitService;

    private BusinessUnitMapper mapper = Mappers.getMapper(BusinessUnitMapper.class);
    private BusinessUnitAssembler assembler = new BusinessUnitAssembler(mapper);

    @Test
    public void getAllShouldReturnAllBusinessUnits() throws Exception {
        List<BusinessUnitDto> businessUnits = Stream.of(
                new BusinessUnit(1L, "Personal"),
                new BusinessUnit(2L, "IT")
        ).map(businessUnit -> assembler.toModel(businessUnit)).collect(Collectors.toList());
        when(businessUnitService.findAll(Pageable.ofSize(10))).thenReturn(new PageImpl<>(businessUnits));
        mockMvc.perform(get("/businessUnits").accept(MediaTypes.HAL_JSON))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.*", hasSize(3)))
                // ... do more jsonPath checking
    }
}

But I'd like to have Spring inject the BusinessUnitAssembler, instead of constructing it myself. I've tried @Importing BusinessUnitAssembler as well as the BusinessUnitMapper and I've also tried it by using a custom @Configuration but I just couldn't get it to work.

So my Question is: How can I let Spring inject my BusinessUnitAssembler into the test for me instead of assembling it myself?

Additional Question: Is it valid to combine the Mapping from Database Entity to DTO in the RepresentationModelAssembler or should those two steps be kept seperate from each other?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source