【问题标题】:How to do Unit testing using Junit4?如何使用 Junit4 进行单元测试?
【发布时间】:2019-12-11 15:16:10
【问题描述】:

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

JWTCreateImpl 类实现 JWTCreate 接口,其中包含抽象方法 loginUser(UserInfoJWT userInfoJWT) 和 generateToken(UUID uuid) 以及一个用于 generateToken() 方法的 String 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;
}

【问题讨论】:

    标签: java jwt junit4


    【解决方案1】:

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

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

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

    对于上述情况,我更喜欢带有 Junit 的 Mockito 参考链接

    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;
        }
    }
    

    【讨论】:

    • 我对 Junit 和 Mocking(如何模拟一个类和方法)一无所知,所以请你用代码解释一下。
    • @kundangupta 根据你的情况编辑了我的答案,让你开始应该很好
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 2021-03-15
    • 2014-01-12
    • 2020-01-06
    • 2021-11-16
    • 1970-01-01
    相关资源
    最近更新 更多