feat(backend): Improve authorization governance and video interactions
This commit is contained in:
+31
-8
@@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.nuaa.video.common.model.vo.Result;
|
||||
import com.nuaa.video.content.dto.*;
|
||||
import com.nuaa.video.content.entity.ContentVideo;
|
||||
import com.nuaa.video.content.entity.ContentVideoPlayRecord;
|
||||
import com.nuaa.video.content.mapper.ContentVideoMapper;
|
||||
import com.nuaa.video.content.service.VideoService;
|
||||
import com.nuaa.video.content.vo.PlayHistoryVO;
|
||||
import com.nuaa.video.content.vo.UploadResultVO;
|
||||
import com.nuaa.video.content.vo.VideoInfoVO;
|
||||
import com.nuaa.video.content.vo.VideoListVO;
|
||||
@@ -62,14 +64,7 @@ public class VideoController {
|
||||
@GetMapping("/public/{id}")
|
||||
public Result<VideoInfoVO> getVideoInfoPublic(@PathVariable Long id, HttpServletRequest request) {
|
||||
Long userId = getUserIdFromRequest(request);
|
||||
Result<VideoInfoVO> result = videoService.getVideoInfo(id, userId);
|
||||
if (result.getData() == null) {
|
||||
return result;
|
||||
}
|
||||
if (result.getData().getPublishTime() == null) {
|
||||
return Result.error("视频暂未公开");
|
||||
}
|
||||
return result;
|
||||
return videoService.getVideoInfo(id, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,6 +218,34 @@ public class VideoController {
|
||||
return videoService.playVideo(recordDTO, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放历史
|
||||
*/
|
||||
@GetMapping("/history")
|
||||
public Result<Page<PlayHistoryVO>> getPlayHistory(
|
||||
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize,
|
||||
HttpServletRequest request) {
|
||||
Long userId = getUserIdFromRequest(request);
|
||||
if (userId == null) {
|
||||
return Result.error("未获取到用户ID");
|
||||
}
|
||||
Page<ContentVideoPlayRecord> page = new Page<>(pageNum, pageSize);
|
||||
return videoService.getPlayHistory(page, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空播放历史
|
||||
*/
|
||||
@DeleteMapping("/history")
|
||||
public Result<Void> clearPlayHistory(HttpServletRequest request) {
|
||||
Long userId = getUserIdFromRequest(request);
|
||||
if (userId == null) {
|
||||
return Result.error("未获取到用户ID");
|
||||
}
|
||||
return videoService.clearPlayHistory(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户视频列表
|
||||
*/
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/**
|
||||
* 用户服务Feign客户端
|
||||
@@ -57,4 +58,30 @@ public interface UserFeignClient {
|
||||
Result<Void> increaseFavoriteCount(@PathVariable("userId") Long userId,
|
||||
@PathVariable("count") Integer count,
|
||||
@RequestHeader("X-Internal-Token") String internalToken);
|
||||
|
||||
/**
|
||||
* 增加用户硬币余额
|
||||
*/
|
||||
@PostMapping("/user/profile/count/coin/increase/{userId}/{count}")
|
||||
Result<Void> increaseCoinCount(@PathVariable("userId") Long userId,
|
||||
@PathVariable("count") Integer count,
|
||||
@RequestHeader("X-Internal-Token") String internalToken);
|
||||
|
||||
/**
|
||||
* 扣减用户硬币余额
|
||||
*/
|
||||
@PostMapping("/user/profile/count/coin/decrease/{userId}/{count}")
|
||||
Result<Void> decreaseCoinCount(@PathVariable("userId") Long userId,
|
||||
@PathVariable("count") Integer count,
|
||||
@RequestHeader("X-Internal-Token") String internalToken);
|
||||
|
||||
/**
|
||||
* 发送用户通知
|
||||
*/
|
||||
@PostMapping("/user/notification/send/{userId}/{type}")
|
||||
Result<Void> sendNotification(@PathVariable("userId") Long userId,
|
||||
@PathVariable("type") Integer type,
|
||||
@RequestParam(value = "content", required = false) String content,
|
||||
@RequestParam(value = "relatedId", required = false) Long relatedId,
|
||||
@RequestHeader("X-Internal-Token") String internalToken);
|
||||
}
|
||||
|
||||
+18
@@ -39,6 +39,24 @@ public class UserFeignClientFallbackFactory implements FallbackFactory<UserFeign
|
||||
log.error("增加用户收藏数量失败,用户ID:{}, 数量:{}", userId, count);
|
||||
return Result.error("更新用户收藏数量失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Void> increaseCoinCount(Long userId, Integer count, String internalToken) {
|
||||
log.error("增加用户硬币余额失败,用户ID:{}, 数量:{}", userId, count);
|
||||
return Result.error("更新用户硬币余额失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Void> decreaseCoinCount(Long userId, Integer count, String internalToken) {
|
||||
log.error("扣减用户硬币余额失败,用户ID:{}, 数量:{}", userId, count);
|
||||
return Result.error("扣减用户硬币余额失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Void> sendNotification(Long userId, Integer type, String content, Long relatedId, String internalToken) {
|
||||
log.error("发送用户通知失败,用户ID:{}, 类型:{}, relatedId:{}", userId, type, relatedId);
|
||||
return Result.error("发送用户通知失败");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.nuaa.video.common.model.vo.Result;
|
||||
import com.nuaa.video.content.dto.*;
|
||||
import com.nuaa.video.content.entity.ContentVideo;
|
||||
import com.nuaa.video.content.entity.ContentVideoPlayRecord;
|
||||
import com.nuaa.video.content.vo.PlayHistoryVO;
|
||||
import com.nuaa.video.content.vo.UploadResultVO;
|
||||
import com.nuaa.video.content.vo.VideoInfoVO;
|
||||
import com.nuaa.video.content.vo.VideoListVO;
|
||||
@@ -135,6 +137,23 @@ public interface VideoService extends IService<ContentVideo> {
|
||||
*/
|
||||
Result<Void> playVideo(PlayRecordDTO recordDTO, Long userId);
|
||||
|
||||
/**
|
||||
* 获取播放历史
|
||||
*
|
||||
* @param page 分页参数
|
||||
* @param userId 用户ID
|
||||
* @return 播放历史
|
||||
*/
|
||||
Result<Page<PlayHistoryVO>> getPlayHistory(Page<ContentVideoPlayRecord> page, Long userId);
|
||||
|
||||
/**
|
||||
* 清空播放历史
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
Result<Void> clearPlayHistory(Long userId);
|
||||
|
||||
/**
|
||||
* 获取用户视频列表
|
||||
*
|
||||
|
||||
+23
-1
@@ -23,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -52,6 +53,8 @@ public class FavoriteServiceImpl extends ServiceImpl<ContentUserFavoriteMapper,
|
||||
.map(favorite -> {
|
||||
FavoriteVO vo = new FavoriteVO();
|
||||
BeanUtils.copyProperties(favorite, vo);
|
||||
int visibleVideoCount = countVisibleFavoriteVideos(favorite.getId());
|
||||
vo.setVideoCount(visibleVideoCount);
|
||||
return vo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
@@ -192,4 +195,23 @@ public class FavoriteServiceImpl extends ServiceImpl<ContentUserFavoriteMapper,
|
||||
|
||||
return Result.success(resultPage);
|
||||
}
|
||||
}
|
||||
|
||||
private int countVisibleFavoriteVideos(Long favoriteId) {
|
||||
List<Long> videoIds = videoFavoriteMapper.selectList(
|
||||
new LambdaQueryWrapper<ContentVideoFavorite>()
|
||||
.eq(ContentVideoFavorite::getFavoriteId, favoriteId)
|
||||
).stream().map(ContentVideoFavorite::getVideoId).collect(Collectors.toList());
|
||||
|
||||
if (videoIds.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Long count = videoMapper.selectCount(
|
||||
new LambdaQueryWrapper<ContentVideo>()
|
||||
.in(ContentVideo::getId, videoIds)
|
||||
.eq(ContentVideo::getStatus, 1)
|
||||
);
|
||||
|
||||
return Math.toIntExact(Objects.requireNonNullElse(count, 0L));
|
||||
}
|
||||
}
|
||||
|
||||
+121
-18
@@ -17,6 +17,7 @@ import com.nuaa.video.content.service.TagService;
|
||||
import com.nuaa.video.content.service.VideoService;
|
||||
import com.nuaa.video.content.utils.VideoProcessor;
|
||||
import com.nuaa.video.content.vo.TagVO;
|
||||
import com.nuaa.video.content.vo.PlayHistoryVO;
|
||||
import com.nuaa.video.content.vo.UploadResultVO;
|
||||
import com.nuaa.video.content.vo.VideoInfoVO;
|
||||
import com.nuaa.video.content.vo.VideoListVO;
|
||||
@@ -32,6 +33,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -48,6 +50,8 @@ import java.util.stream.Collectors;
|
||||
@RequiredArgsConstructor
|
||||
public class VideoServiceImpl extends ServiceImpl<ContentVideoMapper, ContentVideo> implements VideoService {
|
||||
|
||||
private static final ZoneId APP_ZONE_ID = ZoneId.of("Asia/Shanghai");
|
||||
|
||||
@Value("${service.auth.token}")
|
||||
private String internalServiceToken;
|
||||
|
||||
@@ -164,6 +168,12 @@ public class VideoServiceImpl extends ServiceImpl<ContentVideoMapper, ContentVid
|
||||
return Result.error(ResultCode.NOT_FOUND.getCode(), "视频不存在");
|
||||
}
|
||||
|
||||
boolean isOwner = userId != null && userId.equals(video.getUserId());
|
||||
boolean isPublished = Objects.equals(video.getStatus(), VideoStatusEnum.PUBLISHED.getCode());
|
||||
if (!isPublished && !isOwner) {
|
||||
return Result.error(ResultCode.FORBIDDEN.getCode(), "视频暂未公开");
|
||||
}
|
||||
|
||||
// 转换为VO
|
||||
VideoInfoVO videoInfoVO = new VideoInfoVO();
|
||||
BeanUtils.copyProperties(video, videoInfoVO);
|
||||
@@ -205,6 +215,15 @@ public class VideoServiceImpl extends ServiceImpl<ContentVideoMapper, ContentVid
|
||||
|
||||
int coinCount = videoCoinMapper.getUserCoinCount(userId, id);
|
||||
videoInfoVO.setIsCoined(coinCount > 0);
|
||||
|
||||
ContentVideoPlayRecord playRecord = getUserPlayRecord(userId, id);
|
||||
if (playRecord != null) {
|
||||
videoInfoVO.setPlayProgress(playRecord.getPlayTime());
|
||||
videoInfoVO.setIsPlayFinished(Objects.equals(playRecord.getIsFinished(), 1));
|
||||
} else {
|
||||
videoInfoVO.setPlayProgress(0);
|
||||
videoInfoVO.setIsPlayFinished(false);
|
||||
}
|
||||
}
|
||||
|
||||
return Result.success(videoInfoVO);
|
||||
@@ -409,6 +428,7 @@ public class VideoServiceImpl extends ServiceImpl<ContentVideoMapper, ContentVid
|
||||
}}
|
||||
);
|
||||
|
||||
sendVideoLikeNotificationAsync(video, userId);
|
||||
updateUserLikeCountAsync(video.getUserId(), 1);
|
||||
|
||||
return Result.success();
|
||||
@@ -473,25 +493,40 @@ public class VideoServiceImpl extends ServiceImpl<ContentVideoMapper, ContentVid
|
||||
return Result.error("投币总数不能超过2个");
|
||||
}
|
||||
|
||||
// 添加投币记录
|
||||
ContentVideoCoin coin = new ContentVideoCoin();
|
||||
coin.setVideoId(videoId);
|
||||
coin.setUserId(userId);
|
||||
coin.setAmount(amount);
|
||||
coin.setCreateTime(LocalDateTime.now());
|
||||
videoCoinMapper.insert(coin);
|
||||
Result<Void> coinBalanceResult = userFeignClient.decreaseCoinCount(userId, amount, internalServiceToken);
|
||||
if (coinBalanceResult == null || coinBalanceResult.getCode() != 200) {
|
||||
String message = coinBalanceResult != null ? coinBalanceResult.getMessage() : "扣减硬币失败";
|
||||
return Result.error(message);
|
||||
}
|
||||
|
||||
// 发送统计消息,增加投币数
|
||||
videoMessageProducer.sendVideoStatsMessage(
|
||||
new VideoMessageProducer.VideoStatsMessage() {{
|
||||
setVideoId(videoId);
|
||||
setUserId(userId);
|
||||
setAction("coin");
|
||||
setCount(amount);
|
||||
}}
|
||||
);
|
||||
try {
|
||||
// 添加投币记录
|
||||
ContentVideoCoin coin = new ContentVideoCoin();
|
||||
coin.setVideoId(videoId);
|
||||
coin.setUserId(userId);
|
||||
coin.setAmount(amount);
|
||||
coin.setCreateTime(LocalDateTime.now());
|
||||
videoCoinMapper.insert(coin);
|
||||
|
||||
return Result.success();
|
||||
// 发送统计消息,增加投币数
|
||||
videoMessageProducer.sendVideoStatsMessage(
|
||||
new VideoMessageProducer.VideoStatsMessage() {{
|
||||
setVideoId(videoId);
|
||||
setUserId(userId);
|
||||
setAction("coin");
|
||||
setCount(amount);
|
||||
}}
|
||||
);
|
||||
|
||||
return Result.success();
|
||||
} catch (Exception e) {
|
||||
Result<Void> rollbackResult = userFeignClient.increaseCoinCount(userId, amount, internalServiceToken);
|
||||
if (rollbackResult == null || rollbackResult.getCode() != 200) {
|
||||
log.error("投币失败且硬币余额补偿失败,videoId={}, userId={}, amount={}, rollbackResult={}",
|
||||
videoId, userId, amount, rollbackResult);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -673,6 +708,54 @@ public class VideoServiceImpl extends ServiceImpl<ContentVideoMapper, ContentVid
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Page<PlayHistoryVO>> getPlayHistory(Page<ContentVideoPlayRecord> page, Long userId) {
|
||||
Page<ContentVideoPlayRecord> recordPage = playRecordMapper.selectPage(
|
||||
page,
|
||||
new LambdaQueryWrapper<ContentVideoPlayRecord>()
|
||||
.eq(ContentVideoPlayRecord::getUserId, userId)
|
||||
.orderByDesc(ContentVideoPlayRecord::getUpdateTime)
|
||||
);
|
||||
|
||||
List<PlayHistoryVO> historyRecords = recordPage.getRecords().stream()
|
||||
.map(record -> {
|
||||
ContentVideo video = getById(record.getVideoId());
|
||||
if (video == null) {
|
||||
return null;
|
||||
}
|
||||
PlayHistoryVO vo = new PlayHistoryVO();
|
||||
vo.setVideoId(record.getVideoId());
|
||||
vo.setTitle(video.getTitle());
|
||||
vo.setCoverUrl(video.getCoverUrl());
|
||||
vo.setDuration(video.getDuration());
|
||||
vo.setPlayTime(record.getPlayTime());
|
||||
vo.setIsFinished(record.getIsFinished());
|
||||
vo.setUpdateTime(record.getUpdateTime());
|
||||
return vo;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Page<PlayHistoryVO> resultPage = new Page<>();
|
||||
resultPage.setRecords(historyRecords);
|
||||
resultPage.setTotal(recordPage.getTotal());
|
||||
resultPage.setSize(recordPage.getSize());
|
||||
resultPage.setCurrent(recordPage.getCurrent());
|
||||
resultPage.setPages(recordPage.getPages());
|
||||
|
||||
return Result.success(resultPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Result<Void> clearPlayHistory(Long userId) {
|
||||
playRecordMapper.delete(
|
||||
new LambdaQueryWrapper<ContentVideoPlayRecord>()
|
||||
.eq(ContentVideoPlayRecord::getUserId, userId)
|
||||
);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Page<VideoListVO>> getUserVideos(Long userId, Page<ContentVideo> page, Long currentUserId) {
|
||||
VideoQueryDTO queryDTO = new VideoQueryDTO();
|
||||
@@ -885,7 +968,7 @@ public class VideoServiceImpl extends ServiceImpl<ContentVideoMapper, ContentVid
|
||||
stats.put("totalVideos", totalVideos);
|
||||
|
||||
// 今日新增视频
|
||||
LocalDate today = LocalDate.now();
|
||||
LocalDate today = LocalDate.now(APP_ZONE_ID);
|
||||
long todayNewVideos = count(new LambdaQueryWrapper<ContentVideo>()
|
||||
.ge(ContentVideo::getCreateTime, today.atStartOfDay()));
|
||||
stats.put("todayNewVideos", todayNewVideos);
|
||||
@@ -950,6 +1033,26 @@ public class VideoServiceImpl extends ServiceImpl<ContentVideoMapper, ContentVid
|
||||
});
|
||||
}
|
||||
|
||||
private ContentVideoPlayRecord getUserPlayRecord(Long userId, Long videoId) {
|
||||
return playRecordMapper.selectOne(
|
||||
new LambdaQueryWrapper<ContentVideoPlayRecord>()
|
||||
.eq(ContentVideoPlayRecord::getUserId, userId)
|
||||
.eq(ContentVideoPlayRecord::getVideoId, videoId)
|
||||
);
|
||||
}
|
||||
|
||||
private void sendVideoLikeNotificationAsync(ContentVideo video, Long operatorUserId) {
|
||||
runAfterCommitAsync("发送视频点赞通知", () -> {
|
||||
if (!operatorUserId.equals(video.getUserId())) {
|
||||
Result<Void> notifyResult = userFeignClient.sendNotification(video.getUserId(), 1, null, video.getId(), internalServiceToken);
|
||||
if (notifyResult == null || notifyResult.getCode() != 200) {
|
||||
log.warn("发送视频点赞通知失败,videoId={}, ownerUserId={}, operatorUserId={}, result={}",
|
||||
video.getId(), video.getUserId(), operatorUserId, notifyResult);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void runAfterCommitAsync(String action, Runnable task) {
|
||||
Runnable wrappedTask = () -> CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.nuaa.video.content.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 播放历史VO
|
||||
*/
|
||||
@Data
|
||||
public class PlayHistoryVO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 视频ID
|
||||
*/
|
||||
private Long videoId;
|
||||
|
||||
/**
|
||||
* 视频标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 视频封面
|
||||
*/
|
||||
private String coverUrl;
|
||||
|
||||
/**
|
||||
* 视频时长
|
||||
*/
|
||||
private Integer duration;
|
||||
|
||||
/**
|
||||
* 播放进度
|
||||
*/
|
||||
private Integer playTime;
|
||||
|
||||
/**
|
||||
* 是否已看完
|
||||
*/
|
||||
private Integer isFinished;
|
||||
|
||||
/**
|
||||
* 最后播放时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
@@ -68,6 +68,16 @@ public class VideoInfoVO implements Serializable {
|
||||
*/
|
||||
private Integer height;
|
||||
|
||||
/**
|
||||
* 视频格式
|
||||
*/
|
||||
private String format;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
private Long size;
|
||||
|
||||
/**
|
||||
* 分类ID
|
||||
*/
|
||||
@@ -123,6 +133,11 @@ public class VideoInfoVO implements Serializable {
|
||||
*/
|
||||
private Integer danmakuCount;
|
||||
|
||||
/**
|
||||
* 视频状态
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 是否已点赞
|
||||
*/
|
||||
@@ -138,11 +153,31 @@ public class VideoInfoVO implements Serializable {
|
||||
*/
|
||||
private Boolean isCoined;
|
||||
|
||||
/**
|
||||
* 播放进度(秒)
|
||||
*/
|
||||
private Integer playProgress;
|
||||
|
||||
/**
|
||||
* 是否已看完
|
||||
*/
|
||||
private Boolean isPlayFinished;
|
||||
|
||||
/**
|
||||
* 发布时间
|
||||
*/
|
||||
private LocalDateTime publishTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 审核员ID
|
||||
*/
|
||||
@@ -162,4 +197,4 @@ public class VideoInfoVO implements Serializable {
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime reviewTime;
|
||||
}
|
||||
}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.nuaa.video.content.service;
|
||||
|
||||
import com.nuaa.video.content.entity.ContentVideo;
|
||||
import com.nuaa.video.content.feign.UserFeignClient;
|
||||
import com.nuaa.video.content.service.impl.VideoServiceImpl;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@DisplayName("视频通知发送测试")
|
||||
class NotificationDispatchTest {
|
||||
|
||||
@Mock
|
||||
private UserFeignClient userFeignClient;
|
||||
|
||||
@InjectMocks
|
||||
private VideoServiceImpl videoService;
|
||||
|
||||
@Test
|
||||
@DisplayName("视频点赞通知应携带视频ID作为 relatedId")
|
||||
void shouldSendVideoLikeNotificationWithVideoId() {
|
||||
ReflectionTestUtils.setField(videoService, "internalServiceToken", "internal-token");
|
||||
|
||||
ContentVideo video = new ContentVideo();
|
||||
video.setId(300L);
|
||||
video.setUserId(200L);
|
||||
|
||||
ReflectionTestUtils.invokeMethod(videoService, "sendVideoLikeNotificationAsync", video, 100L);
|
||||
|
||||
verify(userFeignClient, timeout(1000)).sendNotification(200L, 1, null, 300L, "internal-token");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user