Как проверить с помощью easymock Capture - PullRequest
3 голосов
/ 01 декабря 2009

У меня есть следующий код

Record rd = registerNewRecord();
<do some processing>
rd.setFinished(true);
updateRecord(rd);

Метод registerNewRecord вызывает метод вставки RecordDao, а updateRecord вызывает метод обновления для того же DAO.

У меня есть следующий код easymock:

Capture<Record> insertRc = new Capture<Record>();
RecordDao.insert(capture(insertRc));
Capture<Record> updateRc= new Capture<Record>();
RecordDao.update(capture(updateRc));

Проблема в том, что, если выше и обновляется тот же экземпляр Record, который был вставлен, обновляется и объект insertRc Capture. Поэтому я не могу утверждать, что готовый флаг установлен на false во время вставки.

Что я делаю не так?

Ответы [ 3 ]

3 голосов
/ 17 декабря 2009

Если ссылки внутри insertRC и updateRC ссылаются на один и тот же объект rd, и это изменяется во время метода update, вы всегда будете видеть, что объект Record завершен.Однако вы можете проверить первый объект Captured до вызова update.

Capture<Record> insertRc = new Capture<Record>();
RecordDao.insert(capture(insertRc));
Record insertedRecord = insertRC.getValue();
org.junit.Assert.assertFalse(insertedRecord.isFinished());

Capture<Record> updateRc= new Capture<Record>();
RecordDao.update(capture(updateRc));
Record updatedRecord = updateRC.getValue();
org.junit.Assert.assertTrue(updatedRecord.isFinished());
2 голосов
/ 03 декабря 2009

Одна из идей заключается в клонировании объекта Record при его захвате.

Реализуйте метод clone() в своем классе Record, а затем реализуйте пользовательский Capture следующим образом:

public class RecordCloneCapture extends Capture<Record> {
    @Override
    public void setValue(Record value) {
        super.setValue(value == null ? null : value.clone());
    }
}

И измените свой тестовый код, чтобы использовать его:

Capture<Record> insertRc = new RecordCloneCapture();
RecordDao.insert(capture(insertRc));
Capture<Record> updateRc= new RecordCloneCapture();
RecordDao.update(capture(updateRc));

Если по какой-то причине вы не можете реализовать clone(), ваш пользовательский класс Capture может просто извлечь необходимую информацию (т. Е. Флаг Завершить запись) в методе setValue и сохранить ее.

0 голосов
/ 14 августа 2012

Захваты не являются ответом. Проблема в том, что ваш код создает новый объект в registerNewRecord (или так я полагаю). Невозможно получить созданный вами объект с помощью new до завершения кода, который вы тестируете. Захваты позволяют задавать вопросы об объекте, созданном / полученном во время выполнения ПОСЛЕ завершения тестируемого метода.

Другая проблема с вашим тестом состоит в том, что ваш тест для текущего метода зависит от кода в методе registerNewRecord() и, возможно, от любого кода в конструкторе объекта Record. Один из способов разорвать эту зависимость и проверить промежуточное состояние объекта Record - это заглушить метод registerNewRecord() и заставить его вернуть макет. Затем вы можете проверить, что были сделаны правильные вызовы для объекта Record, и что ваш код ведет себя корректно для всех возможных возвращаемых значений из объекта записи.

MyClassStub extends MyClass {
  Record registerNewRecord() {
    return recordMock;
  }
}

MyClass objectToTest = new MyClassStub();

public void testSomeMethod() {
   // set expectations, call replay
   objectToTest.someMethod();  // (contains above code that calls registerRecord)
   // asserts/verify
}

Как положительный побочный эффект, вы обнаружите, что ваш тест прерывается только тогда, когда с кодом в тестируемом методе что-то не так, и никогда не прерывается, если проблема заключается в конструкторе Record или registerNewRecord. Однако вы захотите написать второй тест для метода registerNewRecord(), чтобы убедиться, что он работает правильно.

...