【发布时间】:2020-01-06 21:27:39
【问题描述】:
我有以下休息控制器,我正在尝试使用 Mockito 进行测试。
@RestController
public class BackupQueueController {
@Autowired
JmsTemplate jmsTemplate;
@Autowired
SettingsService settingsService;
@Resource
Environment env;
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BackupQueueController.class);
@GetMapping("/eib3/startBackupQueueDraining")
public String startBackupQueueDraining(){
String response= IcisApiServiceConstant.EMPTY;
final String backupQueueEndpoint = env.getProperty("record_order_backup_queue");
final String origQueueEndPoint=env.getProperty("record_order_queue");
final String logPrefix=System.currentTimeMillis()+"-"+" :: BackupQueueController :: startBackupQueueDrain :: " ;
final int totalMessages=getNumberOfMessageInQueue(backupQueueEndpoint);
LOGGER.info(logPrefix+" started .");
Mono.fromRunnable( () -> {
//this block of code will be executed in separate thread!
try {
//get total count of messages in backup queue.
for(int i=0;i<totalMessages;i++) {
//get message from backup queue.
if(StringUtils.equalsIgnoreCase(settingsService.getSettingsProperties().getAllowDrain(),IcisApiServiceConstant.TRUE))
{
String msgPayload = (String) jmsTemplate.receiveAndConvert(backupQueueEndpoint);
AddSalesOrderDocument addSalesOrderDocument = AddSalesOrderDocument.Factory.parse(msgPayload);
String orderId = addSalesOrderDocument.getAddSalesOrder().getDataArea().getSalesOrder().getHeader().getDocumentIds().getTransactionId().getId();
LOGGER.info(logPrefix + " order Id ::" + orderId + " :: request payload :: \n" + msgPayload);
// put message onto original queue.
jmsTemplate.convertAndSend(origQueueEndPoint,msgPayload);
//now thread.sleep
Thread.sleep(Long.parseLong(settingsService.getSettingsProperties().getDrainRate()));
}else{
LOGGER.info(logPrefix+" Allow Drain :: "+settingsService.getSettingsProperties().getAllowDrain() +" :: exiting from backup queue draining process ");
break;
}
}
}catch (Exception e){
LOGGER.error(logPrefix,e.getMessage());
}
}).subscribeOn(Schedulers.newElastic("backupQueue"))
.subscribe();
response+=" draining process has started to drain "+totalMessages+" orders.";
return response;
}
public int getNumberOfMessageInQueue(String queueName) {
Mono<Integer> messageCount= Mono.fromCallable( () -> {
return jmsTemplate.browse(queueName, (session, queueBrowser) ->
Collections.list(queueBrowser.getEnumeration()).size()
);
}).timeout(Duration.ofSeconds(5L)).subscribeOn(Schedulers.elastic());
return messageCount.block(); // Getting null pointer exception while testing //with junit
}
}
控制器使用以下类
@Service
@RefreshScope
public class SettingsService {
@Autowired
private SettingsProperties properties;
public SettingsProperties getSettingsProperties() {
return this.properties;
}
}
@ConfigurationProperties(prefix = "app")
@Component
public class SettingsProperties {
private String name;
private String recordOrderQueue;
private String drainRate;
private String allowDrain;
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(SettingsProperties.class);
public String getDrainRate() {
return drainRate;
}
public void setDrainRate(String drainRate) {
LOGGER.info(getLogPrefix()+ ":: setDrainRate :: drain rate"+drainRate);
this.drainRate = drainRate;
}
public String getRecordOrderQueue() {
return recordOrderQueue;
}
public void setRecordOrderQueue(String recordOrderQueue) {
LOGGER.info(getLogPrefix()+ ":: setRecordOrderQueue :: recordOrderQueue"+recordOrderQueue);
this.recordOrderQueue = recordOrderQueue;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAllowDrain() {
return allowDrain;
}
public void setAllowDrain(String allowDrain) {
LOGGER.info(getLogPrefix()+ ":: setAllowDrain :: allowDrain"+allowDrain);
this.allowDrain = allowDrain;
}
public static String getLogPrefix(){
return System.currentTimeMillis()+" SettingsProperties :: ";
}
@PostConstruct
public void postConstruct() {
LOGGER.info("postConstruct: {}@{} {}",
this.getClass().getSimpleName(), System.identityHashCode(this), this);
}
}
我写了以下测试用例
@RunWith(SpringRunner.class)
public class BackupQueueControllerTest {
@InjectMocks
BackupQueueController backupQueueController= new BackupQueueController();
@Mock
JmsTemplate jmsTemplate;
@Mock
SettingsService settingsService;
@Mock
Environment env;
private static final String ORDER ="<document> <orderId> 1231</orderId></document>";
@Test
public void startBackupQueueDrainingTest(){
when(env.getProperty("record_order_backup_queue")).thenReturn("fake_backup_queue");
when(backupQueueController.getNumberOfMessageInQueue("fake_backup_queue")).thenReturn(10);
when(jmsTemplate.receiveAndConvert("fake_backup_queue")).thenReturn(ORDER);
when(settingsService.getSettingsProperties().getAllowDrain()).thenReturn("yes");
when(settingsService.getSettingsProperties().getDrainRate()).thenReturn("2000");
doNothing().when(jmsTemplate).convertAndSend(anyString(),anyString());
assertEquals(backupQueueController.startBackupQueueDraining(),"draining process has started to drain "+10+" orders.");
}
}
上面的测试用例在 messageCount.block() 处抛出空指针异常
现在我有以下问题。
如何模拟 getNumberOfMessageInQueue() 方法?
如何模拟 settingsService.getSettingsProperties().getAllowDrain() ?
【问题讨论】:
-
1) 我没有看到问题.. 你可以尝试使用这个语法:
doReturn().when()2) 你应该首先这样做:when(settingService.getSettingsProperties()).thenReturn(Something)然后模拟对返回对象的调用:when(Something.getAllowDrain()).thenReturn("yes"); -
@Willem 但是如何模拟 getNumberOfMessageInQueue() 方法?