ServiceResponse mocked 它给出了一个空值而不是预期的这个空值
ServiceResponse mocked which gives a null value and not expected this null
我正在为我的服务编写 j-unit 测试用例,但我无法在其中正确模拟服务响应,这给了我一个空值。有人可以帮我解决这个问题吗?
public ResponseEntity<Void> lockGet(
@ApiParam(value = "Unique identifier for this request.", required = true) @RequestHeader(value = "service-id", required = true) String serviceId,
@ApiParam(value = "Logged in userid.", required = true) @RequestHeader(value = "user-id", required = true) String userId,
@ApiParam(value = "Unique messageid.", required = true) @RequestHeader(value = "message-id", required = true) String messageId,
@RequestHeader(value = "access-token", required = true) String accessToken,
@ApiParam(value = "Unique id of the doamin of the entity", required = true) @RequestParam(value = "lockDomainId", required = true) Long lockDomainId,
@ApiParam(value = "Unique id of the entity to be fetched", required = true) @RequestParam(value = "lockEntityId", required = true) Long lockEntityId,
HttpServletRequest request, HttpServletResponse response) {
ResponseEntity<Void> result = null;
if (request.getAttribute("user-id") != null)
userId = (String) request.getAttribute("user-id");
String logContext = "||" + lockDomainId + "|" + lockEntityId + "||";
ThreadContext.put("context", logContext);
long t1 = System.currentTimeMillis();
LOG.info("Method Entry: lockGet" + logContext);
ServiceRequest serviceRequest = AppUtils.mapGetRequestHeaderToServiceRequest(serviceId, userId, lockDomainId,
lockEntityId);
try {
ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
// set all the response headers got from serviceResponse
HeaderUtils.setResponseHeaders(serviceResponse.getResponseHeaders(), response);
result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
} catch (Exception ex) {
LOG.error("Error in lockGet", ex);
result = new ResponseEntity<Void>(HttpStatus.INTERNAL_SERVER_ERROR);
}
ThreadContext.put("responseTime", String.valueOf(System.currentTimeMillis() - t1));
LOG.info("Method Exit: lockGet");
return result;
}
@Test
public void testLockGetForError() {
request.setAttribute("user-id","TestUser");
ServiceRequest serviceRequest = new ServiceRequest();
serviceRequest.setUserId("TestUser");
ServiceResponse serviceResponse = new ServiceResponse();
LockService service = Mockito.mock(LockService.class);
when(service.getLock(serviceRequest)).thenReturn(serviceResponse);
// ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
ResponseEntity<Void> result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
ResponseEntity<Void> lockGet = lockApiController.lockGet("1234", "TestUser", "TestMessage", "TestTkn", 12345L, 12345L, request, response);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, lockGet.getStatusCode());
}
我尝试了不同的场景,但无法解决这个问题。有人可以帮我吗。提前致谢。
从您提供的代码来看,我看到的问题是您实际上是在模拟 LockService
对象,但是在调用 lockApiController.lockGet
方法时代码实际上并不是 使用模拟 LockService
因为lockApiController有一个它自己的LockService对象。
- 解决这个问题的一种方法是注入模拟的
LockService
使用 @Spy
将对象转换为 lockApiController
对象。这条路
当调用 getLock()
时,它实际上会在
模拟对象并将 return 提供的模拟响应。
所以在你的测试中:
@Test
public void testLockGetForError() {
LockService service = Mockito.mock(LockService.class);
LockApiController lockApiController = Mockito.spy(new LockApiController(service));
request.setAttribute("user-id","TestUser");
ServiceRequest serviceRequest = new ServiceRequest();
serviceRequest.setUserId("TestUser");
ServiceResponse serviceResponse = new ServiceResponse();
when(service.getLock(serviceRequest)).thenReturn(serviceResponse);
// ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
ResponseEntity<Void> result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
ResponseEntity<Void> lockGet = lockApiController.lockGet("1234", "TestUser", "TestMessage", "TestTkn", 12345L, 12345L, request, response);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, lockGet.getStatusCode());
}
因此您可以尝试将模拟的 LockService
对象传递给间谍对象。
- 另一种方法是尝试使用
@InjectMocks
注入模拟
对象进入 LockApiController
.
@InjectMocks
标记应执行注入的字段。 Mockito 将尝试仅通过构造函数注入、setter 注入或 属性 注入来注入模拟——按此顺序。如果任何给定的注入策略失败,那么 Mockito 将不会报告失败。
例如:
@Mock
Map<String, String> wordMap;
@InjectMocks
MyDictionary dic = new MyDictionary();
@Test
public void whenUseInjectMocksAnnotation_thenCorrect() {
Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning");
assertEquals("aMeaning", dic.getMeaning("aWord"));
}
对于class:
public class MyDictionary {
Map<String, String> wordMap;
public MyDictionary() {
wordMap = new HashMap<String, String>();
}
public void add(final String word, final String meaning) {
wordMap.put(word, meaning);
}
public String getMeaning(final String word) {
return wordMap.get(word);
}
}
要使这两个都起作用,您必须有一个构造函数或适当的 setters 来将模拟对象设置为 LockApiController
class.
我正在为我的服务编写 j-unit 测试用例,但我无法在其中正确模拟服务响应,这给了我一个空值。有人可以帮我解决这个问题吗?
public ResponseEntity<Void> lockGet(
@ApiParam(value = "Unique identifier for this request.", required = true) @RequestHeader(value = "service-id", required = true) String serviceId,
@ApiParam(value = "Logged in userid.", required = true) @RequestHeader(value = "user-id", required = true) String userId,
@ApiParam(value = "Unique messageid.", required = true) @RequestHeader(value = "message-id", required = true) String messageId,
@RequestHeader(value = "access-token", required = true) String accessToken,
@ApiParam(value = "Unique id of the doamin of the entity", required = true) @RequestParam(value = "lockDomainId", required = true) Long lockDomainId,
@ApiParam(value = "Unique id of the entity to be fetched", required = true) @RequestParam(value = "lockEntityId", required = true) Long lockEntityId,
HttpServletRequest request, HttpServletResponse response) {
ResponseEntity<Void> result = null;
if (request.getAttribute("user-id") != null)
userId = (String) request.getAttribute("user-id");
String logContext = "||" + lockDomainId + "|" + lockEntityId + "||";
ThreadContext.put("context", logContext);
long t1 = System.currentTimeMillis();
LOG.info("Method Entry: lockGet" + logContext);
ServiceRequest serviceRequest = AppUtils.mapGetRequestHeaderToServiceRequest(serviceId, userId, lockDomainId,
lockEntityId);
try {
ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
// set all the response headers got from serviceResponse
HeaderUtils.setResponseHeaders(serviceResponse.getResponseHeaders(), response);
result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
} catch (Exception ex) {
LOG.error("Error in lockGet", ex);
result = new ResponseEntity<Void>(HttpStatus.INTERNAL_SERVER_ERROR);
}
ThreadContext.put("responseTime", String.valueOf(System.currentTimeMillis() - t1));
LOG.info("Method Exit: lockGet");
return result;
}
@Test
public void testLockGetForError() {
request.setAttribute("user-id","TestUser");
ServiceRequest serviceRequest = new ServiceRequest();
serviceRequest.setUserId("TestUser");
ServiceResponse serviceResponse = new ServiceResponse();
LockService service = Mockito.mock(LockService.class);
when(service.getLock(serviceRequest)).thenReturn(serviceResponse);
// ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
ResponseEntity<Void> result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
ResponseEntity<Void> lockGet = lockApiController.lockGet("1234", "TestUser", "TestMessage", "TestTkn", 12345L, 12345L, request, response);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, lockGet.getStatusCode());
}
我尝试了不同的场景,但无法解决这个问题。有人可以帮我吗。提前致谢。
从您提供的代码来看,我看到的问题是您实际上是在模拟 LockService
对象,但是在调用 lockApiController.lockGet
方法时代码实际上并不是 使用模拟 LockService
因为lockApiController有一个它自己的LockService对象。
- 解决这个问题的一种方法是注入模拟的
LockService
使用@Spy
将对象转换为lockApiController
对象。这条路 当调用getLock()
时,它实际上会在 模拟对象并将 return 提供的模拟响应。
所以在你的测试中:
@Test
public void testLockGetForError() {
LockService service = Mockito.mock(LockService.class);
LockApiController lockApiController = Mockito.spy(new LockApiController(service));
request.setAttribute("user-id","TestUser");
ServiceRequest serviceRequest = new ServiceRequest();
serviceRequest.setUserId("TestUser");
ServiceResponse serviceResponse = new ServiceResponse();
when(service.getLock(serviceRequest)).thenReturn(serviceResponse);
// ServiceResponse serviceResponse = lockService.getLock(serviceRequest);
ResponseEntity<Void> result = new ResponseEntity<Void>(HeaderUtils.getHttpStatus(serviceResponse));
ResponseEntity<Void> lockGet = lockApiController.lockGet("1234", "TestUser", "TestMessage", "TestTkn", 12345L, 12345L, request, response);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, lockGet.getStatusCode());
}
因此您可以尝试将模拟的 LockService
对象传递给间谍对象。
- 另一种方法是尝试使用
@InjectMocks
注入模拟 对象进入LockApiController
.
@InjectMocks
标记应执行注入的字段。 Mockito 将尝试仅通过构造函数注入、setter 注入或 属性 注入来注入模拟——按此顺序。如果任何给定的注入策略失败,那么 Mockito 将不会报告失败。
例如:
@Mock
Map<String, String> wordMap;
@InjectMocks
MyDictionary dic = new MyDictionary();
@Test
public void whenUseInjectMocksAnnotation_thenCorrect() {
Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning");
assertEquals("aMeaning", dic.getMeaning("aWord"));
}
对于class:
public class MyDictionary {
Map<String, String> wordMap;
public MyDictionary() {
wordMap = new HashMap<String, String>();
}
public void add(final String word, final String meaning) {
wordMap.put(word, meaning);
}
public String getMeaning(final String word) {
return wordMap.get(word);
}
}
要使这两个都起作用,您必须有一个构造函数或适当的 setters 来将模拟对象设置为 LockApiController
class.