【发布时间】:2017-09-15 07:42:01
【问题描述】:
我正在测试一个 Spring 控制器,并模拟了我在其中调用的 loginService。
我在控制器响应的单元测试中遇到错误,但正如我在调试模式下看到的那样,比较的两个元素看起来完全一样。
您可以在下面看到显示两个元素相等的调试器图像。
现在让我们看看下面的代码。
被测系统(RestController.class)
@org.springframework.web.bind.annotation.RestController
public class RestController {
@Autowired
LoginService loginService;
...
//METHOD BEING TESTED
@RequestMapping(value = "/login", method = POST)
public ResponseEntity<JsonResponseBody> loginUser(@RequestParam(value ="id") String id, @RequestParam(value="password") String pwd){
try {
Optional<User> userr = loginService.getUserFromDbAndVerifyPassword(id, pwd); //verify the presence into the database
if (userr.isPresent()) {
User user = userr.get(); //get the User from the optional got from the DB
String jwt = loginService.createJwt(user.getId(), user.getUsername(), user.getPermission(), new Date());
//set the jwt token into the header of response
return ResponseEntity.status(HttpStatus.OK).header("jwt", jwt).body(new JsonResponseBody(HttpStatus.OK.value(),"Success! User logged in." + jwt));
}
}catch(UserNotLoggedException e1){ //thrown by loginService#getUserFromDbAndVerifyPassword
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new JsonResponseBody(HttpStatus.FORBIDDEN.value(),"Login failed! Wrong credentials. " + e1.toString()));
}catch(UnsupportedEncodingException e2){ //thrown by loginService#createJwt
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new JsonResponseBody(HttpStatus.FORBIDDEN.value(),"Login failed! Encoding permission token error. " + e2.toString()));
}
//send response to client
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new JsonResponseBody(HttpStatus.FORBIDDEN.value(),"Login failed! No corrispondence found into the database of users."));
}
...
//INNER CLASS USING LOMBOK
@AllArgsConstructor
public class JsonResponseBody{
@Getter @Setter
private int server;
@Getter @Setter
private Object response;
}
...
}
测试类:
@RunWith(MockitoJUnitRunner.class)
public class RestControllerTest {
@InjectMocks
RestController restController;
@Mock
LoginService loginService;
@Test
public void loginUserWithSuccessTest() throws UserNotLoggedException, UnsupportedEncodingException{
User user = new User("BDAGPP32E08F205K", "Pippo Baudo", "ILoveSanRemoEncrypted", "conduttore");
Optional<User> fakeUserOptional = Optional.of(user);
when(loginService.getUserFromDbAndVerifyPassword("BDAGPP32E08F205K","ILoveSanRemo")).thenReturn(fakeUserOptional);
String jwt = "aaaa.bbbb.cccc";
when(loginService.createJwt(eq(user.getId()), eq(user.getUsername()), eq(user.getPermission()), any(Date.class))).thenReturn(jwt);
ResponseEntity serverResponse = restController.loginUser("BDAGPP32E08F205K","ILoveSanRemo");
RestController.JsonResponseBody responseBody = restController.new JsonResponseBody(HttpStatus.OK.value(), "Success! User logged in." + jwt);
assertEquals(serverResponse.getStatusCode(), HttpStatus.OK); //TRUE
boolean areTheyEquals=false;
if((RestController.JsonResponseBody) serverResponse.getBody() == responseBody){
areTheyEquals = true;
}
assertEquals(areTheyEquals, true); //FALSE?!?!?!?!?
assertThat((RestController.JsonResponseBody) serverResponse.getBody(), is(responseBody)); //FALSE?!?!?!
}
}
最后两个断言结果为假。当我调试这个测试时,我发现模拟似乎是正确的,而且在断言之前,被比较的两个对象看起来绝对相等。 JUnit给出的错误是这样的:
java.lang.AssertionError:预期:是 com.example.bytecode.SpringBootJWT.controllers.RestController$JsonResponseBody@587c290d
但是:是 com.example.bytecode.SpringBootJWT.controllers.RestController$JsonResponseBody@4516af24
您可以在下面看到调试器的图像。
【问题讨论】:
-
assertEquals() 不关心两个对象 A 和 B 看起来是否完全相同。它测试 A.equals(B) 是真还是假。所以它完全依赖于JsonResponseBody的equals()方法(如果有的话)的实现。但是请注意,您不是在测试两个对象的相等性。您正在测试 areTheyEquals 与 true 的相等性(用
assertTrue(areTheyEquals)表达会更清楚)。并且仅当您创建的新 responseBody 与响应的主体完全相同的对象(您正在与 == 进行比较)时,areTheyEquals 才设置为 true,这不可能是 true。 -
您正在使用 == 比较对象
-
areTheyEquals 后来被添加,因为我无法理解为什么最后一个断言是错误的。我的问题是:如何调整最后一个断言(不是关于 areTheyEquals 的断言)?
标签: spring unit-testing junit mocking mockito