2015-11-11 2 views
1

Всякий раз, когда я бегу следующий код, который я получаю сообщение об ошибке:Mocking не работает

Wanted but not invoked: 
dynamoDBWriter.addItemsToDynamoTable(
    <any>, 
    <any> 
); 
-> at DynamoDBWriterTest.testAllItemsAdded(DynamoDBWriterTest.java:32) 

However, there were other interactions with this mock: 
dynamoDBWriter.write(
    [{ Item: {} }, { Item: {} }, { Item: {} }, { Item: {} }, { Item: {} }] 
); 
-> at DynamoDBWriterTest.testAllItemsAdded(DynamoDBWriterTest.java:31) 

Ниже мой код:

public class DynamoDBWriterTest { 

    DynamoDBWriter dynamoDbWriter; 

    @Before 
    public void setup() { 
     dynamoDbWriter = mock(DynamoDBWriter.class); 
    } 

    @Test 
    public void testAllItemsAdded() { 
     List<Item> items = new ArrayList<>(); 
     for (int index = 0; index < 5; index++) { 
      items.add(new Item()); 
     } 
     dynamoDbWriter.write(items); 
     verify(dynamoDbWriter, times(5)).addItemsToDynamoTable(any(), any()); 
    } 
} 

код из DynamoDBWriter:

public void write(List<Item> items) { 
     // Initialize the rate limiter to allow capacity units/sec 
     // Since we know that the Item we are putting consumes 1 unit throughput. 
     RateLimiter rateLimiter = RateLimiter.create(1); 

     // Track how much throughput we consume on each put operation 
     for (Item item: items) { 
      // Let the rate limiter wait until our desired throughput "recharges" 
      rateLimiter.acquire(); 
      addItemsToDynamoTable(table, item); 
     } 
    } 

    protected void addItemsToDynamoTable(Table table, Item item) { 
     try { 
      table.putItem(item); 
     } catch (RuntimeException e) { 
      logger.fatal("dynamoDB table.putItem threw exception for:" + tableName, e); 
      throw e; 
     } 
    } 

Спасибо за помощь. Я также добавление фактического «исправленный/рабочий» код, который я использовал:

@Before 
    public void setup() { 
     dynamoDbWriter = spy(DynamoDBWriter....); 
     doNothing().when(dynamoDbWriter).addItemsToDynamoTable(any(), any()); 
    } 

    // Method makes sure that irrespective of the throughput, all the items are added to dynamoDB 
    @Test 
    public void testAllItemsAdded() { 
     List<Item> items = new ArrayList<>(); 
     for (int index = 0; index < 5; index++) { 
      items.add(new Item()); 
     } 
     dynamoDbWriter.write(items); 
     verify(dynamoDbWriter, times(5)).addItemsToDynamoTable(any(), any()); 
    } 

ответ

1

При создании макет DynamoDBWriter, по умолчанию он перекрывает все методы с ничегонеделанием окурки. Когда вы звоните write, замена замещения Mockito позволяет проверить, что write называется, но не любых вызовов, которые выполняет write, делает. Эта реализация никогда не вызывается.

Реальная проблема, конечно, в том, что вы издеваетесь над классом, который вы тестируете. Даже с техническими обходными решениями было бы очень легко протестировать насмешливую структуру, а не издеваться над тестируемым классом. В общем, резервное издевательство над вашими сотрудниками вашей системы под тестированием, а не с вашей системой под самим тестированием. (Смотрите также аналогию JB Nizet от his answer here.)


Тем не менее, если это абсолютно необходимо, вы можете использовать spy реальный экземпляр и выборочно переопределять методы по мере необходимости, или более опасно вы можете использовать thenCallRealMethod на макете :

when(dynamoDbWriter.write(any())).thenCallRealMethod(); 

Для различий между ними, и почему thenCallRealMethod так опасно, см this SO question.

1

Вы издеваетесь над DynamoDBWriter, это означает, что звонки на него на самом деле не вызываются (они вызываются, но внутренний код в них не выполняется, это просто макет). поэтому ошибка, которую вы получаете здесь, потому что только write выполняется, не addItemsToDynamoTable

Вы насмехаясь неправильный объект здесь- если вы хотите проверить DynamoDBWriter, вы не должны издеваться, вы должны издеваться периферийные объекты, используемые им.

В этом случае, я бы макет таблицы, убедитесь, что table.put выполняются 5 раз (не уверен, что из кода, как вы строите DynamoDBWriter и передать таблицу, но я предполагаю, что вы можете передать высмеивала таблицу к нему)

Смежные вопросы