2012-01-06 2 views
1

Я хочу модульного тестирование следующего методаКак использовать thenAnswer с помощью метода, который возвращает аннулируется

public void addRecord(Record record) 
{ 
    Myclass newObj = new Mycalss(); 
    // It creates newObj object, set some values using record object. 
    // and it adds the newObj in daatbase. 
    dataReqDao.persist(newObj); 
}  

Я издевался dataReqDao.persist методом, но, как я могу проверить, если правильные значения копируются в объект newObj? Я хочу получить объект newObj.

Я думаю, что thenAnswer будет подходящим методом для извлечения аргументов метода newObj, но не знает, как использовать его метод, который возвращает void.

Update:
Я попытался

doAnswer(new Answer<Myclass>() { 
       public Myclass answer(InvocationOnMock invocation) { 
        Object[] args = invocation.getArguments(); 
        return (Myclass)args[0]; 
       } 

     }).when(dataReqDao.persist(any(Myclass.class))); 

EDIT:
Это должно быть (спасибо David)

doAnswer(new Answer<Myclass>() { 
        public Myclass answer(InvocationOnMock invocation) { 
         Object[] args = invocation.getArguments(); 
         return (Myclass)args[0]; 
        } 

      }).when(dataReqDao).persist(any(Myclass.class)); 
+0

В вашем обновлении скобки находятся в неправильном месте. Я не уверен, является ли это причиной вашей ошибки, потому что остальная часть выглядит нормально.Поэтому это должно быть 'doAnswer (...) .when (dataReqDao) .persist (...);' Помогает ли это? –

+0

@ Давид: Спасибо, Дэвид. На самом деле я исправил это, но забыл обновить свой вопрос. – xyz

ответ

5

Вы можете создать собственный argument matcher, которая проверяет поля этот объект или использовать argument captor для захвата объекта для дальнейший осмотр.

Например, следующим образом:

ArgumentCaptor<Myclass> c = ArgumentCaptor.forClass(Myclass.class); 
verify(dateReqDao).persist(c.capture()); 
Myclass newObj = c.getValue(); 

... // Validate newObj 
+0

Я попробовал ваше предложение. Пожалуйста, проверьте мои изменения. – xyz

+0

@Ajinkya: Обновлено – axtavt

+0

Это не выполняет умный тест, так как ArgumentCaptor не захватывает это состояние объекта во время вызова, а просто objectId. Поэтому, даже если вы используете сеттеры в своем методе после вызова dao, ваш тест будет зеленым. Но хороший тест должен потерпеть неудачу при каждом функциональном изменении. Я написал свое предложение в качестве ответа на этот пост. – akcasoy

0
Myclass newObj = new Myclass(); 

Эта линия беспокоит меня. Если вы используете инъекцию зависимостей, вам необходимо, чтобы ваш завод отправил вам экземпляр этого объекта. Затем, когда вы создаете свои модульные тесты, вы можете отправить тестовую фабрику в макетный экземпляр MyClass, к которому также может иметь доступ модульный тест. Затем вы можете использовать захватчик axtavt, чтобы убедиться, действительно ли он сделал то, что он должен был делать. Нет ничего плохого в тестировании устройства, как вы это делали, это просто, что any() является слабым, учитывая, что вы знаете, что он передает объект такого типа - то, что вы хотите знать в тесте, заключается в том, является ли объект это тот, который вы намеревались и не был изменен.

1

Вы должны сделать это с thenAnswer (или то, который я лично предпочитаю), так что вы можете утверждать/проверять значения в момент вызова метода, в методе.

when(dataReqDao.persist(newObj)).then(new Answer<Void>() { 
     @Override 
     public Void answer(final InvocationOnMock invocation) { 
      Myclass newObjActual = (Myclass) invocation.getArguments()[0]; 

      // Control 
      assertEquals(..., newObjActual.getX()); 
      assertEquals(..., newObjActual.getY()); 
      return null; 
     } 
    }); 

// Run Test 
x.addRecord(record); 

Вот подробно объяснение: https://akcasoy.wordpress.com/2015/04/09/the-power-of-thenanswer/ (Используйте случай 2)

ArgumentCaptor не испытывает в умным способом. При изменении метода так:

public void addRecord(Record record) 
{ 
    Myclass newObj = new Mycalss(); 
    dataReqDao.persist(newObj); 

    // first persist, than set attributes 
    newObj.setX(..); 
} 

.. ваш тест с Captor еще работает, но он должен потерпеть неудачу. Поскольку ArgumentCaptor не фиксирует это состояние объекта во время вызова, а просто objectId, для захватчика не имеет значения, устанавливаете ли вы свои атрибуты до или после вызова dao. Тем не менее, хороший тест должен потерпеть неудачу при каждом функциональном изменении. Вот моя статья именно об этом:

https://akcasoy.wordpress.com/2015/02/03/how-to-ensure-quality-of-junit-tests/ (выше раскорчевка с тогда является лучшим подходом, хотя, чем тот, с заказовМои подходом)