2013-10-15 6 views
0

Я использую JDK ScheduledThreadPoolExecutor для выполнения задания schdule. Я даю простой код, как показано ниже.Для проблемы Junit: при тестировании нескольких потоков

class Job implements Callable<Void>{ 
     public Long id; 

     @Override 
     public Void call() throws Exception { 
      if (!isOk(id)) { 
       return null; 
      } 

      _context.exe(id); 
      return null; 
     } 


     void setId(Long id) { 
      this.id = id; 
     } 
    } 

Каждый раз, когда я добавить эту работу, чтобы запланировать обслуживание:

public void schedule() { 
    Job job = new Job(); 
    job.setId(1L);; 
    _scheduledExecutor.schedule(job, 1000, TimeUnit.MILLISECONDS) ; 
} 

эта работа задержит ехе метод контекста вызова в. Мой вопрос: я хочу, чтобы метод exe assertconcontext вызывался или нет? Как я могу это сделать?

Что я делаю сейчас, я пытаюсь добавить метод входа в систему() и проверить UT своими глазами. PS: Для этого UT я также пытаюсь издеваться над exe-методом _context, но работа выполняется в другом потоке, поэтому я не могу утверждать его в текущем потоке. у кого есть идея помочь мне написать заявление для этого случая?

В настоящее время я делаю это ниже, но я все еще думаю, что это лучшее решение для этого, просто я не знаю.

_context - это экземпляр контекста, я распространяюсь из этого класса.

public class UTContext extends Context { 
public UTTestCase utTestCase ; 

@Override 
public void exe(Long id) { 
    utTestCase.setIsCall(true); 
} 

public void setUtTestCase(UTTestCase utTestCase) { 
    this.utTestCase = utTestCase; 
} 

}

Тогда я буду утверждать isCall вар в UT.

Есть ли у кого-нибудь хорошие идеи для этого, PLS дать мне ответ. Большое спасибо.

+0

PS: То, что я пытаюсь сделать: создать _context класса расширить существующие _context и перезаписать выездную метод ехе, я установлю этот экземпляр обратно к тестируемому классу, когда он создал , и в этом поддельном exe-методе я напишу код, чтобы изменить класс, на который подано заявление для проверки, вызывается или нет. Но я все еще думаю, что это плохой способ проверить это. Любая хорошая идея для этого. Спасибо всем, кто дает мне идеи. – Bensson

ответ

2

Вы тестируете кусок середины иерархии вызовов, а именно код создателя потока/диспетчера. Это означает, что вам нужно управлять кодом сверху и тестировать либо сверху, либо снизу. Существует несколько моделей того, как вы это делаете.

Либо у вас инструмент внизу (exe(id)), либо вы измеряете сверху. При задержке планирования измерение с вершины становится очень трудным.

Есть ли у exe() побочные эффекты? Этот побочный эффект можно проверить из вашего тестового кода? Можете ли вы сделать вывод о одном вызове exe()? Можете ли вы сделать вывод более одного? Если ответ на любой из них «нет», вам придется идти дальше.

@ RamonBoza предоставил хорошее решение.

Вы также можете создать проверяемую версию класса Job, таким образом:.

class JobUT extends Job { 
    @Override 
    public Void call() throws Exception { 
    Void result = super.call(); 
    // Report error if wrong return result 
    } 
} 

(я знаю, что есть проблемы с кодом выше как Void не обрабатывается должным образом, я не в состоянии к refactor your code.)

Вы также можете достичь той же цели, используя Aspect Oriented Programming, где вы перехватите вызов после его завершения и выполните те же тесты.

+0

Спасибо за то, что вы принесли мне много хорошего. Предоставляемый код настраивается. exe (id) не имеет никакого другого побочного эффекта, и мне нужен mock этот метод, он запущен сложный env .. Перезаписать класс JOB является хорошей точкой, но проблема в том, что класс задания является локальной переменной в моем исходном коде. Я не могу его вводить, когда я разрушаю UT. May AspectJ может помочь в этом, но проблема в том, что AspectJ jar не существует в текущем проекте. наш проект имеет длительный процесс применения новой банки в исходном коде. Итак, можете ли вы получить более подробную информацию о том, как заставить «перезаписать класс JOB» работать? – Bensson

+0

или вы хотите, чтобы я перезаписывал 'public void schedule()' одновременно. Поэтому я почти создал 2 новых класса для этого UT. это хорошая практика? – Bensson

+0

Не «Перезаписать» - «Переопределить». Расширяя класс и переопределяя выбранные методы, вы фактически открываете класс для проверки, но делаете это без использования интроспекции. –

0

Для утверждения при многопоточности я обычно создаю потоки «N» и назначаю другое значение для каждого потока.

Затем присоедините их все, и в конце проверьте, сохранены ли данные каждой нити? например.

Представьте, что вы создаете 1000 потоков, которые хранят целое число в базе данных, поэтому после того, как эти 1000 потоков завершились, вы должны проверить, хранятся ли в базе данных все данные.

Более жесткий тип теста предназначен для тестирования интеграции и должен выполняться с различными сценариями и промежуточным программным обеспечением (OpenNebula, облако Amazon и т. Д.).

+0

Моя проблема в том, что мы не используем какую-либо БД, и я не хочу менять какой-либо исходный код для модульного теста. И вы можете видеть поток, созданный в методе расписания, который я не хочу изменять, поэтому не могу решить мою проблему. Мой вопрос заключается в том, как писать UT для этого кода без изменения выходного поведения. – Bensson

0

После дня сервера, я знаю, как проверить его сейчас. Я прикрепил другой вопрос для справки:

Assert times of expectLastCall

Service service = EasyMock.createMock(Service.class); 
service.applyInitialDump(entities); 
EasyMock.expectLastCall().times(100); 

processor.processInitialDump(entities) 
EasyMock.verify(service); 
Смежные вопросы