Merge "complete_postservice_test_code"
diff --git a/src/main/java/com/example/g8backend/controller/PostController.java b/src/main/java/com/example/g8backend/controller/PostController.java
index 7b7b7c7..3557af2 100644
--- a/src/main/java/com/example/g8backend/controller/PostController.java
+++ b/src/main/java/com/example/g8backend/controller/PostController.java
@@ -54,4 +54,51 @@
     public List<Post> getPostsByUserId(@PathVariable("userId") Long userId) {
         return postService.getPostsByUserId(userId);
     }
+
+    @PutMapping("/{postId}")
+    public ResponseEntity<?> updatePost(@PathVariable("postId") Long postId, @RequestBody Post post) {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        long userId = (long) authentication.getPrincipal();
+        Post existingPost = postService.getById(postId);
+        
+        if (existingPost == null) {
+            return ResponseEntity.status(500).body("Post not found.");
+        }
+        if (existingPost.getUserId() != userId) {
+            return ResponseEntity.status(403).body("You are not authorized to update this post.");
+        }
+        
+        post.setPostId(postId);
+        post.setUserId(userId);
+        postService.updateById(post);
+        return ResponseEntity.ok().body("Post updated successfully.");
+    }
+
+    @GetMapping("/type/{postType}")
+    public ResponseEntity<?> getPostsByType(@PathVariable String postType) {
+        List<Post> posts = postService.getPostsByType(postType);
+        return ResponseEntity.ok().body(posts);
+    }
+
+    @PostMapping("/{postId}/like")
+    public ResponseEntity<?> likePost(@PathVariable Long postId) {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        long userId = (long) authentication.getPrincipal();
+        postService.likePost(userId, postId);
+        return ResponseEntity.ok().body("Post liked successfully.");
+    }
+
+    @DeleteMapping("/{postId}/like")
+    public ResponseEntity<?> unlikePost(@PathVariable Long postId) {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        long userId = (long) authentication.getPrincipal();
+        postService.unlikePost(userId, postId);
+        return ResponseEntity.ok().body("Post unliked successfully.");
+    }
+
+    @GetMapping("/{postId}/likes")
+    public ResponseEntity<?> getPostLikeCount(@PathVariable Long postId) {
+        Long likeCount = postService.getPostLikeCount(postId);
+        return ResponseEntity.ok().body(likeCount);
+    }
 }
diff --git a/src/main/java/com/example/g8backend/service/IPostService.java b/src/main/java/com/example/g8backend/service/IPostService.java
index 58c13dc..f81053e 100644
--- a/src/main/java/com/example/g8backend/service/IPostService.java
+++ b/src/main/java/com/example/g8backend/service/IPostService.java
@@ -2,9 +2,14 @@
 
 import com.example.g8backend.entity.Post;
 import com.baomidou.mybatisplus.extension.service.IService;
-
 import java.util.List;
 
 public interface IPostService extends IService<Post> {
     List<Post> getPostsByUserId(Long userId);
+    Post createPost(Post post);
+    Post updatePost(Post post);
+    List<Post> getPostsByType(String postType);
+    Long getPostLikeCount(Long postId);
+    void likePost(Long userId, Long postId);
+    void unlikePost(Long userId, Long postId);
 }
diff --git a/src/main/java/com/example/g8backend/service/impl/PostServiceImpl.java b/src/main/java/com/example/g8backend/service/impl/PostServiceImpl.java
index 90d353a..09a471e 100644
--- a/src/main/java/com/example/g8backend/service/impl/PostServiceImpl.java
+++ b/src/main/java/com/example/g8backend/service/impl/PostServiceImpl.java
@@ -1,21 +1,63 @@
 package com.example.g8backend.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.example.g8backend.entity.Post;
 import com.example.g8backend.mapper.PostMapper;
 import com.example.g8backend.service.IPostService;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
-
+import java.sql.Timestamp;
 import java.util.List;
 
 @Service
 public class PostServiceImpl extends ServiceImpl<PostMapper, Post> implements IPostService {
-    @Resource
-    private PostMapper postMapper;
+    
+    private final PostMapper postMapper;
+
+    public PostServiceImpl(PostMapper postMapper) {
+        this.postMapper = postMapper;
+        this.baseMapper = postMapper; // 重要:设置 baseMapper
+    }
 
     @Override
     public List<Post> getPostsByUserId(Long userId) {
         return postMapper.getPostsByUserId(userId);
     }
+
+    @Override
+    public Post createPost(Post post) {
+        post.setCreatedAt(new Timestamp(System.currentTimeMillis()));
+        save(post);
+        return post;
+    }
+
+    @Override 
+    public Post updatePost(Post post) {
+        updateById(post);
+        return getById(post.getPostId());
+    }
+
+    @Override
+    public List<Post> getPostsByType(String postType) {
+        QueryWrapper<Post> wrapper = new QueryWrapper<>();
+        wrapper.eq("post_type", postType);
+        return list(wrapper);
+    }
+
+    @Override
+    public Long getPostLikeCount(Long postId) {
+        // TODO: 需要实现post_likes表的查询
+        return 0L;
+    }
+
+    @Override
+    public void likePost(Long userId, Long postId) {
+        // TODO: 需要实现post_likes表的插入
+    }
+
+    @Override
+    public void unlikePost(Long userId, Long postId) {
+        // TODO: 需要实现post_likes表的删除
+    }
 }
diff --git a/src/main/resources/mapper/PostMapper.xml b/src/main/resources/mapper/PostMapper.xml
index bc4debe..c1dbda7 100644
--- a/src/main/resources/mapper/PostMapper.xml
+++ b/src/main/resources/mapper/PostMapper.xml
@@ -1,3 +1,4 @@
+.xml
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
@@ -6,4 +7,18 @@
     <select id="getPostsByUserId" resultType="com.example.g8backend.entity.Post">
         SELECT * FROM posts WHERE user_id = #{userId}
     </select>
+
+    <select id="getPostLikeCount" resultType="java.lang.Long">
+        SELECT COUNT(*) FROM post_likes WHERE post_id = #{postId}
+    </select>
+
+    <insert id="likePost">
+        INSERT INTO post_likes (user_id, post_id)
+        VALUES (#{userId}, #{postId})
+    </insert>
+
+    <delete id="unlikePost">
+        DELETE FROM post_likes 
+        WHERE user_id = #{userId} AND post_id = #{postId}
+    </delete>
 </mapper>
\ No newline at end of file
diff --git a/src/test/java/com/example/g8backend/service/PostServiceTest.java b/src/test/java/com/example/g8backend/service/PostServiceTest.java
new file mode 100644
index 0000000..6f54177
--- /dev/null
+++ b/src/test/java/com/example/g8backend/service/PostServiceTest.java
@@ -0,0 +1,152 @@
+package com.example.g8backend.service;
+
+import com.example.g8backend.entity.Post;
+import com.example.g8backend.mapper.PostMapper;
+import com.example.g8backend.service.impl.PostServiceImpl;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(SpringExtension.class)
+@DisplayName("帖子服务测试")
+class PostServiceTest {
+
+    @Mock
+    private PostMapper postMapper;
+
+    private PostServiceImpl postService;
+
+    private Post testPost;
+
+    @BeforeEach
+    void setUp() {
+        MockitoAnnotations.openMocks(this);
+        postService = new PostServiceImpl(postMapper);
+        testPost = createTestPost();
+    }
+
+    private Post createTestPost() {
+        Post post = new Post();
+        post.setPostId(1L);
+        post.setUserId(1L);
+        post.setPostTitle("测试标题");
+        post.setPostContent("测试内容");
+        post.setCreatedAt(new Timestamp(System.currentTimeMillis()));
+        return post;
+    }
+
+    @Test
+    @DisplayName("创建帖子-成功")
+    void save_ShouldSucceed() {
+        // Arrange
+        when(postMapper.insert(any(Post.class))).thenReturn(1);
+
+        // Act
+        boolean result = postService.save(testPost);
+
+        // Assert
+        assertTrue(result);
+        verify(postMapper).insert(testPost);
+    }
+
+    @Test
+    @DisplayName("获取帖子-通过ID存在")
+    void getById_WhenExists_ShouldReturnPost() {
+        // Arrange
+        when(postMapper.selectById(1L)).thenReturn(testPost);
+
+        // Act
+        Post result = postService.getById(1L);
+
+        // Assert
+        assertNotNull(result);
+        assertEquals(testPost.getPostId(), result.getPostId());
+        verify(postMapper).selectById(1L);
+    }
+
+    @Test
+    @DisplayName("获取帖子-通过ID不存在")
+    void getById_WhenNotExists_ShouldReturnNull() {
+        // Arrange
+        when(postMapper.selectById(999L)).thenReturn(null);
+
+        // Act
+        Post result = postService.getById(999L);
+
+        // Assert
+        assertNull(result);
+        verify(postMapper).selectById(999L);
+    }
+
+    @Test
+    @DisplayName("更新帖子-成功")
+    void updateById_ShouldSucceed() {
+        // Arrange
+        when(postMapper.updateById(any(Post.class))).thenReturn(1);
+
+        // Act
+        boolean result = postService.updateById(testPost);
+
+        // Assert
+        assertTrue(result);
+        verify(postMapper).updateById(testPost);
+    }
+
+    @Test
+    @DisplayName("删除帖子-成功")
+    void removeById_ShouldSucceed() {
+        // Arrange
+        when(postMapper.deleteById(1L)).thenReturn(1);
+
+        // Act
+        boolean result = postService.removeById(1L);
+
+        // Assert
+        assertTrue(result);
+        verify(postMapper).deleteById(1L);
+    }
+
+    @Test
+    @DisplayName("获取用户帖子列表")
+    void getPostsByUserId_ShouldReturnPosts() {
+        // Arrange
+        List<Post> expectedPosts = Arrays.asList(testPost);
+        when(postMapper.getPostsByUserId(1L)).thenReturn(expectedPosts);
+
+        // Act
+        List<Post> result = postService.getPostsByUserId(1L);
+
+        // Assert
+        assertNotNull(result);
+        assertFalse(result.isEmpty());
+        assertEquals(testPost.getPostId(), result.get(0).getPostId());
+        verify(postMapper).getPostsByUserId(1L);
+    }
+
+    @Test
+    @DisplayName("获取用户帖子-空列表")
+    void getPostsByUserId_WhenNoPosts_ShouldReturnEmptyList() {
+        // Arrange
+        when(postMapper.getPostsByUserId(999L)).thenReturn(Arrays.asList());
+
+        // Act
+        List<Post> result = postService.getPostsByUserId(999L);
+
+        // Assert
+        assertNotNull(result);
+        assertTrue(result.isEmpty());
+        verify(postMapper).getPostsByUserId(999L);
+    }
+}
\ No newline at end of file