当前位置: 首页 > 知识库问答 >
问题:

Mockito Junit测试-“需要但未调用;然而,这个模拟“错误”还有其他交互作用

莘聪
2023-03-14
@Test
public void testTimeoutFunction() throws Exception {
    Response response = getResponseForTest(); 
    when(requestAdapter.transform(itemRequest)).thenReturn(Request);

    when(dataProvider
        .provide(any(Request.class)))
        .thenAnswer((Answer<Response>) invocation -> {
            Thread.sleep(1000000);
            return response;
        });

    processor = spy(getProcessor());

    when(itemRequest.getRequestContext()).thenReturn(itemRequestContext);
    when(itemRequestContext.getMetadata()).thenReturn(requestContextMetadata);

    List<Item> output = processor.getItemist(ITEM_ID, itemRequest);

    assertTrue(output.isEmpty());
    verify(processor, times(1)).processRequest(Request);
    verify(processor, times(1)).responseTimedOutCount();
}
public class Process {

    @VisibleForTesting
    void  responseTimedOutCount() {
    //log metrics
    }

    private CompletableFuture<Response> getResponseAsync(final ScheduledExecutorService delayer,
                                                                             final ItemRequest itemRequest) {
        return timeoutWithTimeoutFunction(delayer, EXECUTION_TIMEOUT, TimeUnit.MILLISECONDS,
                CompletableFuture.supplyAsync(() -> getResponseWithTimeoutFunction(itemRequest), executorService),
                Response.emptyResponse(), () -> responseTimedOutCount());
    }


    private Response getResponseWithTimeoutFunction(final ItemRequest itemRequest) {
        //do something and return response
    }

   public List<Item> getItemList(final String id, final ItemRequest itemRequest) throws Exception {

        final ScheduledExecutorService delayer = Executors.newScheduledThreadPool(1);
        Response response;
        if(validateItemId(id){
            try {
                response = getResponseAsync(delayer, itemRequest).get();
            } catch (final Throwable t) {
                response = Response.emptyResponse();
            } finally {
                delayer.shutdown();
            }
            return transform(response, id).getItems(); 
        } else {
            return null;
        }
    }
   }
public static <T> CompletableFuture<T> timeoutWithTimeoutFunction(final ScheduledExecutorService es,
                                                                      final long timeout,
                                                                      final TimeUnit unit,
                                                                      final CompletableFuture<T> f,
                                                                      final T defaultValue,
                                                                      final Runnable r) {
        final Runnable timeoutFunction = () -> {
            boolean timedOut = f.complete(defaultValue);
            if (timedOut && r != null) {
                r.run();
            }
        };

        es.schedule(timeoutFunction, timeout, unit);
        return f;
    }

Junit异常:

   Wanted but not invoked: process.responseTimedOutCount(); -> at processTest.testTimeoutFunction(processTest.java:377) 
   However, there were exactly 3 interactions with this mock: 
   process.getItemList( ITEM_ID, itemRequest ); -> at processTest.testTimeoutFunction(processTest.java:373) 
   process.validateItemId( ITEM_ID ); -> at process.getItemList(process.java:133) 
   process.processRequest( request ); -> at process.getResponseWithTimeoutFunction(process.java:170)

共有1个答案

孟鸿德
2023-03-14

要测试超时,您可能想要模拟要测试超时的调用。相对于它应该永远进行的测试的持续时间。

when(dataProvider
    .provide(any(Request.class)))
    .thenAnswer((Answer<Response>) invocation -> {
        Thread.sleep(FOREVER);
        return response;
    });

验证应该有一个线程处理超时。当超时很长时,您可能应该确保它是可配置的,以允许快速测试。类似验证(mock,timeout(LONGER_THAN_REAL_TIMEOUT)).someCall()

确保在总测试持续时间上设置一个超时时间,以确保当前或未来的失败不会减慢您的构建速度。

 类似资料: