Модульный тест Async Deferred Result Controller зависает навсегда - PullRequest
0 голосов
/ 07 декабря 2018

Метод контроллера, который я тестирую

@GetMapping("/customers")
@ResponseBody
public DeferredResult<ResponseEntity<Resources<Resource<Customer>>>> getAllCustomers(
        @PageableDefault(page = 0, size = 20) @SortDefault.SortDefaults({
                @SortDefault(sort = "name", direction = Direction.ASC) }) Pageable pageable,
        PagedResourcesAssembler<Customer> assembler, HttpServletRequest request) {

    DeferredResult<ResponseEntity<Resources<Resource<Customer>>>> response = new DeferredResult<>(
            Long.valueOf(1000000));
    response.onTimeout(() -> response
            .setErrorResult(ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT).body("Request timed out.")));
    response.onError((Throwable t) -> {
        response.setErrorResult(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occured."));
    });

    ListenableFuture<Page<Customer>> future = customerService.findAll(pageable);

    future.addCallback(new ListenableFutureCallback<Page<Customer>>() {

        @Override
        public void onSuccess(Page<Customer> result) {
            Link self = new Link(
                    ServletUriComponentsBuilder.fromRequestUri(request).buildAndExpand().toUri().toString(),
                    "self");
            LOGGER.debug("Generated Self Link {} for Customer Resource Collection", self.getHref());
            if (result.hasContent())
                response.setResult(
                        ResponseEntity.ok(assembler.toResource(result, customerResourceAssembler, self)));
            else
                response.setErrorResult(ResponseEntity.notFound());
            LOGGER.debug("Returning Response with {} customers", result.getNumber());
        }

        @Override
        public void onFailure(Throwable ex) {
            LOGGER.error("Could not retrieve customers due to error", ex);
            response.setErrorResult(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("Could not save customers list due to server error."));
        }

    });

    return response;
}

модульный тест

@RunWith(SpringRunner.class)
@WebMvcTest(CustomerController.class)
@EnableSpringDataWebSupport
@Import({ CustomerResourceAssember.class, BranchResourceAssembler.class, InvoiceResourceAssembler.class,
        CustomerAsyncService.class })
public class CustomerControllerTests {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    CustomerAsyncService customerService;

    @MockBean
    private CustomerRepository customerRepository;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testWhenNoCustomersThenReturnsEmptyHALDocument() throws Exception {

        // Given
        BDDMockito.given(customerRepository.findAll(PageRequest.of(0, 20)))
                .willReturn(new PageImpl<Customer>(Collections.emptyList()));

        // When
        MvcResult result = mockMvc.perform(get("/customers").accept(MediaTypes.HAL_JSON_VALUE)).andDo(print())
                .andExpect(request().asyncStarted())
                .andExpect(request().asyncResult(new PageImpl<Customer>(Collections.emptyList()))).andReturn();

        // Then
        mockMvc.perform(asyncDispatch(result)).andExpect(status().isOk());

    }

Этот тест еще раз завершен, даже не истекает время ожидания в моей IDE, я должен его убитькаждый раз, когда я запускаю его, если запустить все приложение, эта конечная точка /customers выдает 404, когда в приложение не добавлено ни одного клиента.

Что мне нужно сделать, чтобы этот тест завершился, CustomerService в конечном счете, call вызывает CustomerRepository, над которым я издевался, потому что не мог понять, как смоделировать метод асинхронного вызова к сервису.класс обслуживания клиентов выглядит следующим образом:

@Async
@Service
public class CustomerAsyncService {

    private CustomerRepository customerRepository;

    @Autowired
    public CustomerAsyncService(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    @Transactional(readOnly = true, isolation = Isolation.SERIALIZABLE)
    public ListenableFuture<Page<Customer>> findAll(Pageable pageable) {
        return AsyncResult.forValue(customerRepository.findAll(pageable));
    }

Я надеялся, что насмешка над методом Repository поможет.Как мне посмеяться над вызовом асинхронной службы

1 Ответ

0 голосов
/ 19 декабря 2018

Мой плохой неправильно использовал насмешки, это сработало

@RunWith(SpringRunner.class)
@WebMvcTest(CustomerController.class)
@Import({ CustomerResourceAssember.class, BranchResourceAssembler.class, InvoiceResourceAssembler.class,
        CustomerAsyncService.class })
public class CustomerControllerTests {

    @MockBean
    private CustomerRepository customerRepository;

    @InjectMocks
    CustomerAsyncService customerService = new CustomerAsyncService(customerRepository);

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        JacksonTester.initFields(this, objectMapper);
    }

    @Test
    public void testReturnsNotFoundForEmptyGetAllCustomersResult() throws Exception {

        // Given
        Page<Customer> emptyPage = new PageImpl<Customer>(Collections.emptyList());
        BDDMockito.given(customerRepository.findAll(any(Pageable.class))).willReturn(emptyPage);

        // When
        MvcResult result = mockMvc.perform(get("/customers")).andExpect(request().asyncStarted()).andDo(print()).andReturn();

        // Then
        mockMvc.perform(asyncDispatch(result)).andDo(print()).andExpect(status().isNotFound());
    }


}
...