一、redis简介
1. 内存型key - value 数据库,也叫缓存数据库,无需sql随存随用。
详细教程:https://www.runoob.com/redis/redis-tutorial.html
2. 安装、启动
下载地址:https://github.com/MSOpenTech/redis/releases
解压后目录,启动redis-service,启动redis-cli即可;
3. 数据结构
String,Hash,List,Set,Zset
二、为何使用,测试使用有何好处
研发使用主要减轻服务器的压力,读取数据效率高,速度快;那么测试为何使用呢?
场景引入:
登录系统成功后生成ur-accid,ur-token,后续所有用例都需要使用ur-accid、ur-token在header中做一个身份验证。
疑问:
我之前写接口用例时总是不知道如果处理token这类的信息最简单,也尝试过很多方法,比如:在类中提取,比如作为在base层提取给下面的接口用。
最简单:
使用redis只需要在登录用例中提取一次,就可以满足全部用例的使用,随存随取,使用方便,用后无需管理,下次登录自动覆盖;
另外,redis中可以存放任何数据,token,cookie,或者其他一些测试中反复用到的东西都可以放到里面。
三、如何使用
场景:登录系统成功后生成ur-accid,ur-token,后续所有用例都需要使用ur-accid、ur-token在header中做一个身份验证;
第一步:提取 ur-accid和ur-token
第二部:存放 RedisUtils.set("token", ur_token);
第三步:使用 RedisUtils.get("token")
示例:
public class MissionTest extends BaseApi{
@Test
public void loginTest001() throws Exception {
String url="http://xxx.xxx.com/api/xx/user/login";
Map headers=new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("ur-ct", "10");
Map params=new HashMap<>();
params.put("mobile", "13082832552");
params.put("deviceId", "fdjfuerjdnjadskfjdsaf");
params.put("smsCode", "9527");
String todyStr=FastjsonUtils.toJson(params);
CloseableHttpResponse response = RestClient.post(url, todyStr, null, headers);
String responseString = EntityUtils.toString(response.getEntity());
//提取ur-accid,ur-token
JSONObject res = FastjsonUtils.toJsonObject(responseString);
String ur_token = FastjsonUtils.toMap(res.getString("data")).get("ur-token");
//存到redis中
RedisUtils.set("token", ur_token);
Object userInfo = FastjsonUtils.toMap(res.getString("data")).get("userInfo");
String ur_accid = FastjsonUtils.toMap(userInfo.toString()).get("accid");
RedisUtils.set("accid", ur_accid);
//断言
String mobile= FastjsonUtils.toMap(userInfo.toString()).get("mobile");
Assert.assertEquals(mobile, "13082832552");
}
@Test
public void getJoinApply002() throws Exception{
String url="http://xxx.xxx.com/api/xx/ent/getJoinApply";
//设置header 直接使用redis中的token 和 accid
Map headers=new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("ur-ct", "10");
headers.put("ur-token", RedisUtils.get("token"));
headers.put("ur-accid", RedisUtils.get("accid"));
Map params=new HashMap<>();
params.put("page","1");
params.put("pageSize","50");
params.put("role","0");
String todyStr=FastjsonUtils.toJson(params);
CloseableHttpResponse response = RestClient.post(url, todyStr, null, headers);
String responseString = EntityUtils.toString(response.getEntity());
JSONObject jsonObject=FastjsonUtils.toJsonObject(responseString);
Assert.assertEquals(jsonObject.getString("msg"), "ok");
}
}
把上面的代码header部分进行优化,每次写用例太爽
可登录redis客户端,看下存的数据:
四、Redis工具类示例,可根据需要进行设置
public class RedisUtils {
private static final Logger logger = LoggerFactory.getLogger(RedisUtils.class);
private static JedisPool pool;
static {
String redisHost = PropertiesUtils.getConfigValue("redis.host", "127.0.0.1");
String redisPort = PropertiesUtils.getConfigValue("redis.port", "6379");
JedisPoolConfig poolConfig = new JedisPoolConfig();
// 连接最大等待时间,超时会抛出连接异常
poolConfig.setMaxWaitMillis(Long.parseLong(PropertiesUtils.getConfigValue("redis.maxWaitMillis", "5000")));
// 池中最大可用的连接数
poolConfig.setMaxTotal(Integer.parseInt(PropertiesUtils.getConfigValue("redis.maxTotal", "500")));
// 空闲时池中保存的最大连接数
poolConfig.setMaxIdle(Integer.parseInt(PropertiesUtils.getConfigValue("redis.maxIdle", "100")));
// 空闲时池中保存的最小连接数
poolConfig.setMinIdle(Integer.parseInt(PropertiesUtils.getConfigValue("redis.minIdle", "20")));
poolConfig.setTestOnReturn(true);
//每隔30秒进行空闲回收
poolConfig.setTimeBetweenEvictionRunsMillis(Long.parseLong(PropertiesUtils.getConfigValue("redis.timeBetweenEvictionRunsMillis","30000")));
//过空闲1分钟才能被扫描回收
poolConfig.setMinEvictableIdleTimeMillis(Long.parseLong(PropertiesUtils.getConfigValue("redis.minEvictableIdleTimeMillis", "60000")));
// 保证得到的redis实例都是可用的实例
poolConfig.setTestOnBorrow(true);
pool = new JedisPool(poolConfig, redisHost, Integer.parseInt(redisPort));
}
/**
* get value
* @param key 键
* @return 值
*/
public static String get(String key) {
Jedis jedis = pool.getResource();
try {
if(jedis != null) {
return jedis.get(key);
}
} catch (Exception e) {
// 打印错误日志
logger.error(e.getMessage(), e);
} finally {
// 关闭redis链接,释放资源
close(jedis);
}
return null;
}
/**
* set value
* @param key 键
* @param value 值
*/
public static void set(String key, String value) {
Jedis jedis = pool.getResource();
try {
if(jedis != null) {
jedis.set(key, value);
}
} catch (Exception e) {
// 打印错误日志
logger.error(e.getMessage(), e);
} finally {
// 关闭redis链接,释放资源
close(jedis);
}
}
/**
* set value with live time
* @param key 键
* @param value 值
* @param liveTime 存活时长(秒)
*/
public static void setex(String key, String value, int liveTime) {
Jedis jedis = pool.getResource();
try {
if(jedis != null) {
jedis.setex(key, liveTime, value);
}
} catch (Exception e) {
// 打印错误日志
logger.error(e.getMessage(), e);
} finally {
// 关闭redis链接,释放资源
close(jedis);
}
}
public static String hget(String key, String field){
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis != null && jedis.hexists(key, field)) {
// 刷新过期时间,每次都刷新会不会效率低下? => 获取该key的ttl时间,如果小于10秒,则重置,否则直接返回
Long ttl = jedis.ttl(key);
if(ttl < 10) {
jedis.expire(key, 20 * 60);
}
return jedis.hget(key, field);
}
}catch(Exception e){
// 打印错误日志
logger.error(e.getMessage(), e);
} finally {
// 关闭redis链接,释放资源
close(jedis);
}
return null;
}
public static void hmset(String key, Map hash){
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis != null){
jedis.hmset(key, hash);
jedis.expire(key, 20 * 60); // 20分钟,和ssoTicket的失效时间保存一致
}
}catch(Exception e){
// 打印错误日志
logger.error(e.getMessage(), e);
} finally {
// 关闭redis链接,释放资源
close(jedis);
}
}
// 释放资源
private static void close(Jedis jedis) {
if(jedis != null) {
// 关闭链接
jedis.close();
}
}
private RedisUtils(){}
}