java - 如何使用Junit4进行单元测试?

标签 java jwt junit4

我创建了一个下面给出的 JWTCreateImpl 类,以使用generatToken()方法生成jwt token ,并使用loginUser()方法响应jwt字符串。 loginUser() 方法将电子邮件和密码作为来自前端的参数。该电子邮件与数据库中存在的电子邮件进行比较,如果电子邮件不存在,则错误响应将变为“电子邮件不存在”,类似地,密码不匹配。最后,如果特定 ID 存在电子邮件和密码,则从数据库中提取结果并仅传递用户的 uuid 来生成 token ,响应将是 jwt 字符串。我想使用 Junit4 对该类执行单元测试,如何使用 Junit4 编写测试用例?

JWTCreateImpl 类实现 JWTCreate 接口(interface),其中包含抽象方法 loginUser(UserInfoJWT userInfoJWT) 和generateToken(UUID uuid) 以及一个在generateToken() 方法中使用的字符串 JWT_TOKEN_KEY 主要与 HMAC256 算法一起使用。 UserInfoJWT 是一个 POJO 类,其中包含用户的电子邮件和密码。

ResponseJWT 是一个 POJO 类,其中包含 UserToken 和 errorResponse。

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.knoldus.magad.jwt.api.JWTCreate;
import com.knoldus.magad.jwt.model.ResponseJWT;
import com.knoldus.magad.jwt.model.UserInfoJWT;
import com.knoldus.magad.dao.model.UserInfo;
import com.knoldus.magad.user.api.UserInfoProcessingAPI;

import org.apache.log4j.Logger;


import java.io.UnsupportedEncodingException;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class JWTCreateImpl implements JWTCreate {
private static final Logger LOGGER = Logger.getLogger(JWTCreateImpl.class);
private UserInfo existingUser;
private ResponseJWT response;
private  UserInfoProcessingAPI userInfoProcessingAPI;
private static final String NO_USER_EMAIL = "Email doesn't exists..";
private static  final String LOGIN_UNSUCCESSFUL = "Wrong Password";


@Override
public CompletableFuture<String>loginUser(final UserInfoJWT userInfoJWT) {
    return userInfoProcessingAPI.getUserInfo(userInfoJWT.getUserEmail()).thenApply(result -> {
        existingUser = result.orElse(null);
        if (existingUser == null) {
            response = ResponseJWT.builder().errorResponse(NO_USER_EMAIL).build();
        } else {
            final String dataBasePassword = existingUser.getUserPassword();
            if (userInfoJWT.getUserPassword().equals(dataBasePassword)) {
                response = ResponseJWT.builder().userToken(generateToken(existingUser.getUuid())).build();
            } else {
                response = ResponseJWT.builder().errorResponse(LOGIN_UNSUCCESSFUL).build();
            }
        }
        return response.toString();
    });
}
@Override
public String generateToken(final UUID uuid) {
    try {
        final Algorithm algorithm = Algorithm.HMAC256(JWT_TOKEN_KEY);
        final Date expirationDate = Date.from(ZonedDateTime.now().plusHours(24).toInstant());
        final Date issuedAt = Date.from(ZonedDateTime.now().toInstant());
        final String id = String.valueOf(uuid);
        final String issuer = "MagADAuth";
        return JWT.create()
                .withIssuedAt(issuedAt) // Issue date.
                .withExpiresAt(expirationDate) // Expiration date.
                .withClaim("userId", id)
                .withIssuer(issuer) // Issuer of the token.
                .sign(algorithm); // And the signing algorithm.
    } catch (UnsupportedEncodingException | JWTCreationException e) {
        LOGGER.error(e.getMessage(), e);
    }
    return null;
}

最佳答案

众所周知,单元测试是独立测试应用程序的一小部分,这意味着在我们的案例中,方法应该独立测试

在您的情况下,JWTCreateImpl类的loginUser方法实际上依赖于对象UserInfoJWT,UserInfoProcessingAPI,因此为了对loginUser方法进行单元测试

  • 我们需要模拟 UserInfoJWT 类,以便它向我们返回电子邮件,这实际上是该方法所需的输入
  • 我们还需要模拟 UserInfoProcessingAPI,以便它返回 User
  • 最后,我们还需要在单元测试用例中调用真实方法loginUser方法(此外,我们需要通过单独的单元测试来测试每个可能的条件的loginUser方法)
  • 对于generateToken方法,我们还需要为单元测试提供UUID模拟。

对于上述情况,我更喜欢使用 Mockito 和 Junit 引用链接

What is Mocking? Why to use Mockito?

根据评论进行编辑

@RunWith(MockitoJUnitRunner.class)
public class JWTCreateImplTest {

    /* class under test should not be mocked */
    private JWTCreateImpl jwtCreateImpl;

    /* Mocking UserInfoProcessingAPI as it is dependency of JWTCreateImpl */
    @Mock
    private UserInfoProcessingAPI infoProcessingAPI;

    /*Mockito method which setup everything before test actually start (All Object Initialization can be done here */
    @Before
    public void setup() {
        jwtCreateImpl = new JWTCreateImpl();
    }

    /* Testing Happy flow */
    @Test
    public void testNotNullJwtToken() {
        Mockito.when(infoProcessingAPI.getUserInfo(getUser().getUserEmail())).thenReturn(getAppUser());
        CompletableFuture<String> jwtToken = jwtCreateImpl.loginUser(getUser());
        Assert.assertNotNull(jwtToken);
    }

    /* Testing when null email is passed */
    @Test
    public void testJwtTokenWithNullEmail() {
        /* this will return null as there are no object exists with email <null> */
        Mockito.when(infoProcessingAPI.getUserInfo(null)).thenReturn(null);
        CompletableFuture<String> jwtToken = jwtCreateImpl.loginUser(getUser());
        /* response of NO_USER_EMAIL should be checked here */
        Assert.assertEquals("NO_USER_EMAIL",jwtToken);
    }

    /*TODO */

    /* similarly you need to check
    * when password is null <AND>
    * when password doesn't match with requester password <AND>
    * generateToken method should be checked for positive scenrio as well as case scenrio where it will throw
    * UnsupportedEncodingException or JWTCreationException
    * all of these in independant test cases
    */

    private UserInfoJwt getUser(){
        UserInfoJwt userInfoJwt = new UserInfoJwt();
        userInfoJwt.setUserEmail("name@java.com");
        userInfoJwt.setUserEmail("myPassword");
        return userInfoJwt;
    }

    private AppUser getAppUser() {

        AppUser user = new AppUser();
        user.setId(1);
        user.setName("name");
        user.setEmail("appuser@java.com");
        return user;
    }
}

关于java - 如何使用Junit4进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57335875/

相关文章:

java - 如何使用 Canvas 在 Java 中制作一组可点击的圆圈?

java - UcanAccess 和 Java 出现 BIG_INT 错误

java - jsfunit 与 junit 4

java - 命令行参数是否有任何命名约定?

java - JComponent 相对于 JPanel 的坐标系

ssl - 需要使用 https、jwt 和 bcrypt 确认安全性

jakarta-ee - 如何使用 JWE 生成 JWT/JWS

security - JWT RS256、RS384、RS512 算法有什么区别?

java - 使用@MockBean 或@Autowired 在测试中模拟

java - Netbeans 上的 Junit 不起作用