JUnit,当两个对象看起来完全相同时,assertEquals为

时间:2017-09-15 07:42:01

标签: spring unit-testing junit mocking mockito

我正在测试一个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

您可以在下面看到调试器的图像。

The Debugger Tab shows how the two elements being compared (serverResponse.body and responseBody) seem exactly equal. But the last two asserts are false

1 个答案:

答案 0 :(得分:1)

此块中有两种不同类型的断言:

boolean areTheyEquals=false;
if((RestController.JsonResponseBody) serverResponse.getBody() == responseBody){
    areTheyEquals = true;
}
assertEquals(areTheyEquals, true); //FALSE?!?!?!?!?
assertThat((RestController.JsonResponseBody) serverResponse.getBody(), is(responseBody)); //FALSE?!?!?!

目前还不清楚你的代码是否达到了第二个断言(assertThat(...)),但有一些事情是明确的:

  • 使用==断言相等只有在比较相同实例
  • 时才有效
  • 如果assertThat((RestController.JsonResponseBody) serverResponse.getBody(), is(responseBody))失败,则equals()上的RestController.JsonResponseBody方法认为这两个实例不同,所以:
    • equals()上的RestController.JsonResponseBody方法无法按预期执行
    • 这两个RestController.JsonResponseBody实例真的不同
    • (最有可能)equals()上没有RestController.JsonResponseBody方法,所以它只是向父母调用super来评估对象相等性

我建议:

  1. equals()上添加RestController.JsonResponseBody方法,或者只使用Mockito的refEq()来应用简单的基于反思的相等检查
  2. 删除此断言:assertEquals(areTheyEquals, true);