From 6161f8abfb4990e79889ed9aa2ccdad510957c49 Mon Sep 17 00:00:00 2001
From: zhuangtianxiang <2913129173@qq.com>
Date: Mon, 6 Jan 2025 14:24:47 +0800
Subject: [PATCH] =?UTF-8?q?test(iot):=20=E6=96=B0=E5=A2=9E=20IoT=E7=9B=B8?=
 =?UTF-8?q?=E5=85=B3=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- 新增 Device、Event、Product、Property 相关的测试用例- 更新 Param 相关的测试用例
- 新增对应的 Builder 类方便测试数据的构建
- 优化测试用例的结构,增加 setup 和 teardown 方法
---
 .../tsl/service/impl/PropertyServiceImpl.java |   3 +
 .../resources/mappers/iot/EventMapper.xml     |   2 +-
 .../edu/gateway/domain/iot/EventBuilder.java  |  48 ++++++++
 .../edu/gateway/domain/iot/ParamBuilder.java  |   8 +-
 .../gateway/domain/iot/PropertyBuilder.java   |  44 ++++++++
 .../domain/notice/UserMessageBuilder.java     |  37 +++++++
 .../rest/iot/DeviceControllerTest.java        |  99 +++++++++++++++++
 .../gateway/rest/iot/EventControllerTest.java | 100 +++++++++++++++++
 .../rest/iot/ProductControllerTest.java       |  97 ++++++++++++++++
 .../rest/iot/PropertyControllerTest.java      | 104 ++++++++++++++++++
 .../gateway/rest/iot/ServeControllerTest.java | 101 +++++++++++++++++
 .../rest/notice/BulletinControllerTest.java   |   8 +-
 .../notice/UserMessageControllerTest.java     |  78 +++++++++++++
 .../gateway/service/iot/EventServiceTest.java | 101 +++++++++++++++++
 .../gateway/service/iot/ParamServiceTest.java |  55 +++++----
 .../service/iot/PropertyServiceTest.java      |  75 +++++++++++++
 16 files changed, 923 insertions(+), 37 deletions(-)
 create mode 100644 src/test/java/com/zsc/edu/gateway/domain/iot/EventBuilder.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/domain/iot/PropertyBuilder.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/domain/notice/UserMessageBuilder.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/rest/iot/DeviceControllerTest.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/rest/iot/EventControllerTest.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/rest/iot/ProductControllerTest.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/rest/iot/PropertyControllerTest.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/rest/iot/ServeControllerTest.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/rest/notice/UserMessageControllerTest.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/service/iot/EventServiceTest.java
 create mode 100644 src/test/java/com/zsc/edu/gateway/service/iot/PropertyServiceTest.java

diff --git a/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/service/impl/PropertyServiceImpl.java b/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/service/impl/PropertyServiceImpl.java
index 8de44bf..3b633c2 100644
--- a/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/service/impl/PropertyServiceImpl.java
+++ b/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/service/impl/PropertyServiceImpl.java
@@ -8,6 +8,7 @@ import com.zsc.edu.gateway.modules.iot.tsl.repo.PropertyRepository;
 import com.zsc.edu.gateway.modules.iot.tsl.service.PropertyService;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * @author 15864
@@ -32,12 +33,14 @@ public class PropertyServiceImpl extends ServiceImpl<PropertyRepository, Propert
      * 更新属性
      */
     @Override
+    @Transactional
     public Property update(PropertyDto dto, Long id) {
         Property property = baseMapper.selectById(id);
         if (property == null) {
             throw new RuntimeException("Serve not found with id: " + id);
         }
         mapper.convert(dto, property);
+        baseMapper.updateById(property);
         return property;
     }
 
diff --git a/src/main/resources/mappers/iot/EventMapper.xml b/src/main/resources/mappers/iot/EventMapper.xml
index 70b2382..dc4cc6c 100644
--- a/src/main/resources/mappers/iot/EventMapper.xml
+++ b/src/main/resources/mappers/iot/EventMapper.xml
@@ -34,7 +34,7 @@
                ip.name       as param_name,
                ip.remark     as param_remark
         from iot_event e
-                 left join iot_param ip on ep.id = ip.foreign_id
+                 left join iot_param ip on e.id = ip.foreign_id
             and ip.foreign_type = 1
         where e.id = #{id}
     </select>
diff --git a/src/test/java/com/zsc/edu/gateway/domain/iot/EventBuilder.java b/src/test/java/com/zsc/edu/gateway/domain/iot/EventBuilder.java
new file mode 100644
index 0000000..b4ff18e
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/domain/iot/EventBuilder.java
@@ -0,0 +1,48 @@
+package com.zsc.edu.gateway.domain.iot;
+
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Event;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
+
+import java.util.List;
+
+public class EventBuilder extends BaseParamBuilder {
+    private Long productId;
+    private Event.Type type;
+    private String name;
+    private String identifier;
+
+    public static EventBuilder builder() {
+        return new EventBuilder();
+    }
+
+    public EventBuilder setProductId(Long productId) {
+        this.productId = productId;
+        return this;
+    }
+
+    public EventBuilder setType(Event.Type type) {
+        this.type = type;
+        return this;
+    }
+
+    public EventBuilder setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public EventBuilder setIdentifier(String identifier) {
+        this.identifier = identifier;
+        return this;
+    }
+
+    public Event build() {
+        Event event = new Event();
+        event.setName(name);
+        event.setIdentifier(identifier);
+        event.setProductId(productId);
+        event.setType(type);
+        return event;
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/domain/iot/ParamBuilder.java b/src/test/java/com/zsc/edu/gateway/domain/iot/ParamBuilder.java
index b1b5495..a87cfc9 100644
--- a/src/test/java/com/zsc/edu/gateway/domain/iot/ParamBuilder.java
+++ b/src/test/java/com/zsc/edu/gateway/domain/iot/ParamBuilder.java
@@ -5,7 +5,7 @@ import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
 
 public class ParamBuilder extends BaseParamBuilder {
     public DataType dataType;
-    public String uint;
+    public String name;
     public Param.Type type;
     public Param.ForeignType foreignType;
     public Long foreignId;
@@ -24,8 +24,8 @@ public class ParamBuilder extends BaseParamBuilder {
         return this;
     }
 
-    public ParamBuilder uint(String uint) {
-        this.uint = uint;
+    public ParamBuilder name(String name) {
+        this.name = name;
         return this;
     }
 
@@ -42,7 +42,7 @@ public class ParamBuilder extends BaseParamBuilder {
     public Param build() {
         Param param = new Param();
         param.setForeignId(foreignId);
-        param.setUint(uint);
+        param.setName(name);
         param.setType(type);
         param.setForeignType(foreignType);
         param.setDataType(dataType);
diff --git a/src/test/java/com/zsc/edu/gateway/domain/iot/PropertyBuilder.java b/src/test/java/com/zsc/edu/gateway/domain/iot/PropertyBuilder.java
new file mode 100644
index 0000000..eddc9f9
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/domain/iot/PropertyBuilder.java
@@ -0,0 +1,44 @@
+package com.zsc.edu.gateway.domain.iot;
+
+import com.zsc.edu.gateway.modules.iot.tsl.entity.DataType;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Property;
+
+public class PropertyBuilder extends BaseParamBuilder {
+    private Long productId;
+    private DataType dataType;
+    private Property.IoType ioType;
+    private String name;
+
+    public static PropertyBuilder builder() {
+        return new PropertyBuilder();
+    }
+
+    public PropertyBuilder setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public PropertyBuilder setProductId(Long productId) {
+        this.productId = productId;
+        return this;
+    }
+
+    public PropertyBuilder setDataType(DataType dataType) {
+        this.dataType = dataType;
+        return this;
+    }
+
+    public PropertyBuilder setIoType(Property.IoType ioType) {
+        this.ioType = ioType;
+        return this;
+    }
+
+    public Property build() {
+        Property property = new Property();
+        property.setName(name);
+        property.setProductId(productId);
+        property.setDataType(dataType);
+        property.setIoType(ioType);
+        return property;
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/domain/notice/UserMessageBuilder.java b/src/test/java/com/zsc/edu/gateway/domain/notice/UserMessageBuilder.java
new file mode 100644
index 0000000..cf89b31
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/domain/notice/UserMessageBuilder.java
@@ -0,0 +1,37 @@
+package com.zsc.edu.gateway.domain.notice;
+
+
+import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
+
+public class UserMessageBuilder {
+    public Long userId;
+    public Long messageId;
+    public Boolean isRead;
+
+    public static UserMessageBuilder builder() {
+        return new UserMessageBuilder();
+    }
+
+    public UserMessageBuilder setUserId(Long userId) {
+        this.userId = userId;
+        return this;
+    }
+
+    public UserMessageBuilder setMessageId(Long messageId) {
+        this.messageId = messageId;
+        return this;
+    }
+
+    public UserMessageBuilder setIsRead(Boolean isRead) {
+        this.isRead = isRead;
+        return this;
+    }
+
+    public UserMessage build() {
+        UserMessage userMessage = new UserMessage();
+        userMessage.setUserId(userId);
+        userMessage.setMessageId(messageId);
+        userMessage.setIsRead(isRead);
+        return userMessage;
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/rest/iot/DeviceControllerTest.java b/src/test/java/com/zsc/edu/gateway/rest/iot/DeviceControllerTest.java
new file mode 100644
index 0000000..26be28b
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/rest/iot/DeviceControllerTest.java
@@ -0,0 +1,99 @@
+package com.zsc.edu.gateway.rest.iot;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zsc.edu.gateway.MockMvcConfigBase;
+import com.zsc.edu.gateway.domain.iot.DeviceBuilder;
+import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
+import com.zsc.edu.gateway.modules.iot.device.controller.DeviceController;
+import com.zsc.edu.gateway.modules.iot.device.dto.DeviceDto;
+import com.zsc.edu.gateway.modules.iot.device.entity.Device;
+import com.zsc.edu.gateway.modules.iot.device.service.DeviceService;
+import com.zsc.edu.gateway.modules.iot.record.service.RecordDataService;
+import org.assertj.core.util.Lists;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Spy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@WebMvcTest(DeviceController.class)
+public class DeviceControllerTest extends MockMvcConfigBase {
+    @Spy
+    private static Device device1;
+    private static Device device2;
+    @MockBean
+    private DeviceService service;
+    @MockBean
+    private RecordDataService recordDataService;
+
+    @BeforeAll
+    static void beforeAll() {
+        device1 = DeviceBuilder.aDevice().online(true).name("Device 1").build();
+        device1.setId(1L);
+        device2 = DeviceBuilder.aDevice().online(false).name("Device 2").build();
+        device2.setId(2L);
+    }
+
+    @Test
+    void create() throws Exception {
+        DeviceDto dto = new DeviceDto();
+        dto.setProductId(121L);
+        dto.setName(device1.getName());
+        when(service.create(any(DeviceDto.class))).thenReturn(device1);
+        mockMvc.perform(post("/api/rest/device")
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).create(any(DeviceDto.class));
+    }
+
+    @Test
+    void list() throws Exception {
+        List<Device> devices = Lists.newArrayList(device1, device2);
+        when(service.page(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(new Page<Device>().setRecords(devices).setTotal((long) devices.size()));
+
+        mockMvc.perform(get("/api/rest/device").with(user(userDetails)))
+                .andExpect(status().isOk())
+                .andDo(print());
+
+        verify(service).page(any(Page.class), any(LambdaQueryWrapper.class));
+    }
+
+    @Test
+    void update() throws Exception {
+        DeviceDto dto = new DeviceDto();
+        dto.setProductId(121L);
+        dto.setName(device1.getName());
+        when(service.update(any(DeviceDto.class), anyLong())).thenReturn(device1);
+        mockMvc.perform(patch("/api/rest/device/{id}", device1.getId())
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).update(any(DeviceDto.class), anyLong());
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/rest/iot/EventControllerTest.java b/src/test/java/com/zsc/edu/gateway/rest/iot/EventControllerTest.java
new file mode 100644
index 0000000..ef25bcc
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/rest/iot/EventControllerTest.java
@@ -0,0 +1,100 @@
+package com.zsc.edu.gateway.rest.iot;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zsc.edu.gateway.MockMvcConfigBase;
+import com.zsc.edu.gateway.domain.iot.EventBuilder;
+import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
+import com.zsc.edu.gateway.modules.iot.tsl.controller.EventController;
+import com.zsc.edu.gateway.modules.iot.tsl.dto.EventDto;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Event;
+import com.zsc.edu.gateway.modules.iot.tsl.service.EventService;
+import org.assertj.core.util.Lists;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Spy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@WebMvcTest(EventController.class)
+public class EventControllerTest extends MockMvcConfigBase {
+    @Spy
+    private static Event event1;
+    private static Event event2;
+    @MockBean
+    private EventService service;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @BeforeAll
+    static void beforeAll() {
+        event1 = EventBuilder.builder().setName("Event 1").setIdentifier("Description 1").build();
+        event1.setId(1L);
+        event2 = EventBuilder.builder().setName("Event 2").setIdentifier("Description 2").build();
+        event2.setId(2L);
+    }
+
+    @Test
+    void create() throws Exception {
+        EventDto dto = new EventDto();
+        dto.setProductId(121L);
+        dto.setName(event1.getName());
+        dto.setIdentifier(event1.getIdentifier());
+        dto.setOutputs(null);
+        when(service.create(any(EventDto.class))).thenReturn(event1);
+        mockMvc.perform(post("/api/rest/tsl/event")
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).create(any(EventDto.class));
+    }
+
+    @Test
+    void list() throws Exception {
+        List<Event> events = Lists.newArrayList(event1, event2);
+        when(service.page(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(new Page<Event>().setRecords(events).setTotal((long) events.size()));
+        mockMvc.perform(get("/api/rest/tsl/event").with(user(userDetails)))
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).page(any(Page.class), any(LambdaQueryWrapper.class));
+    }
+
+    @Test
+    void update() throws Exception {
+        EventDto dto = new EventDto();
+        dto.setProductId(121L);
+        dto.setName("Event UPDATE");
+        dto.setIdentifier(event1.getIdentifier());
+        dto.setOutputs(null);
+        when(service.update(any(EventDto.class), anyLong())).thenReturn(event1);
+        mockMvc.perform(patch("/api/rest/tsl/event/{id}", event1.getId())
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).update(any(EventDto.class), anyLong());
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/rest/iot/ProductControllerTest.java b/src/test/java/com/zsc/edu/gateway/rest/iot/ProductControllerTest.java
new file mode 100644
index 0000000..8bb520f
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/rest/iot/ProductControllerTest.java
@@ -0,0 +1,97 @@
+package com.zsc.edu.gateway.rest.iot;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zsc.edu.gateway.MockMvcConfigBase;
+import com.zsc.edu.gateway.domain.iot.ProductBuilder;
+import com.zsc.edu.gateway.modules.iot.product.controller.ProductController;
+import com.zsc.edu.gateway.modules.iot.product.dto.ProductDto;
+import com.zsc.edu.gateway.modules.iot.product.entity.Product;
+import com.zsc.edu.gateway.modules.iot.product.service.ProductService;
+import org.assertj.core.util.Lists;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Spy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@WebMvcTest(ProductController.class)
+public class ProductControllerTest extends MockMvcConfigBase {
+    @Spy
+    private static Product product1;
+    private static Product product2;
+    @MockBean
+    private ProductService service;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @BeforeAll
+    static void beforeAll() {
+        product1 = ProductBuilder.bProduct().name("Product 1").productType("Description 1").build();
+        product1.setId(1L);
+        product2 = ProductBuilder.bProduct().name("Product 2").productType("Description 2").build();
+        product2.setId(2L);
+    }
+
+    @Test
+    void create() throws Exception {
+        ProductDto dto = new ProductDto();
+        dto.setProductType(product1.getProductType());
+        dto.setName(product1.getName());
+        dto.setParams(null);
+        when(service.create(any(ProductDto.class))).thenReturn(product1);
+        mockMvc.perform(post("/api/rest/product")
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).create(any(ProductDto.class));
+    }
+
+    @Test
+    void list() throws Exception {
+        List<Product> products = Lists.newArrayList(product1, product2);
+        when(service.page(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(new Page<Product>().setRecords(products).setTotal((long) products.size()));
+        mockMvc.perform(get("/api/rest/product").with(user(userDetails)))
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).page(any(Page.class), any(LambdaQueryWrapper.class));
+    }
+
+    @Test
+    void update() throws Exception {
+        ProductDto dto = new ProductDto();
+        dto.setProductType(product1.getProductType());
+        dto.setName(product1.getName());
+        dto.setParams(null);
+        when(service.update(any(ProductDto.class), anyLong())).thenReturn(product1);
+        mockMvc.perform(patch("/api/rest/product/{id}", product1.getId())
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).update(any(ProductDto.class), anyLong());
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/rest/iot/PropertyControllerTest.java b/src/test/java/com/zsc/edu/gateway/rest/iot/PropertyControllerTest.java
new file mode 100644
index 0000000..ce5a668
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/rest/iot/PropertyControllerTest.java
@@ -0,0 +1,104 @@
+package com.zsc.edu.gateway.rest.iot;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zsc.edu.gateway.MockMvcConfigBase;
+import com.zsc.edu.gateway.domain.iot.PropertyBuilder;
+import com.zsc.edu.gateway.modules.iot.tsl.controller.PropertyController;
+import com.zsc.edu.gateway.modules.iot.tsl.dto.PropertyDto;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.DataType;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Property;
+import com.zsc.edu.gateway.modules.iot.tsl.service.PropertyService;
+import org.assertj.core.util.Lists;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Spy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@WebMvcTest(PropertyController.class)
+public class PropertyControllerTest extends MockMvcConfigBase {
+    @Spy
+    private static Property property1;
+    private static Property property2;
+    @MockBean
+    private PropertyService service;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @BeforeAll
+    static void beforeAll() {
+        property1 = PropertyBuilder.builder().setName("PROPERTY_NAME_1").setProductId(121L)
+                .setIoType(Property.IoType.READ_WRITE).setDataType(DataType.DATE).build();
+        property1.setId(1L);
+        property2 = PropertyBuilder.builder().setName("PROPERTY_NAME_2").setProductId(121L)
+                .setIoType(Property.IoType.READ_WRITE).setDataType(DataType.DATE).build();
+        property2.setId(2L);
+    }
+
+    @Test
+    void create() throws Exception {
+        PropertyDto dto = new PropertyDto();
+        dto.setProductId(121L);
+        dto.setName(property1.getName());
+        dto.setIdentifier("Identifier 1");
+        dto.setDataType(DataType.DATE);
+        dto.setIoType(Property.IoType.READ_WRITE);
+        when(service.create(any(PropertyDto.class))).thenReturn(property1);
+        mockMvc.perform(post("/api/rest/tsl/property")
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).create(any(PropertyDto.class));
+    }
+
+    @Test
+    void list() throws Exception {
+        List<Property> properties = Lists.newArrayList(property1, property2);
+        when(service.page(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(new Page<Property>().setRecords(properties).setTotal((long) properties.size()));
+        mockMvc.perform(get("/api/rest/tsl/property").with(user(userDetails)))
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).page(any(Page.class), any(LambdaQueryWrapper.class));
+    }
+
+    @Test
+    void update() throws Exception {
+        PropertyDto dto = new PropertyDto();
+        dto.setProductId(121L);
+        dto.setName("PROPERTY_UPDATE");
+        dto.setIdentifier("Identifier 1");
+        dto.setDataType(DataType.DATE);
+        dto.setIoType(Property.IoType.READ_WRITE);
+        when(service.update(any(PropertyDto.class), anyLong())).thenReturn(property1);
+        mockMvc.perform(patch("/api/rest/tsl/property/{id}", property1.getId())
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).update(any(PropertyDto.class), anyLong());
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/rest/iot/ServeControllerTest.java b/src/test/java/com/zsc/edu/gateway/rest/iot/ServeControllerTest.java
new file mode 100644
index 0000000..3927756
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/rest/iot/ServeControllerTest.java
@@ -0,0 +1,101 @@
+package com.zsc.edu.gateway.rest.iot;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zsc.edu.gateway.MockMvcConfigBase;
+import com.zsc.edu.gateway.domain.iot.ServeBuilder;
+import com.zsc.edu.gateway.modules.iot.tsl.controller.ServeController;
+import com.zsc.edu.gateway.modules.iot.tsl.dto.ServeDto;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Serve;
+import com.zsc.edu.gateway.modules.iot.tsl.service.ServeService;
+import org.assertj.core.util.Lists;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Spy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@WebMvcTest(ServeController.class)
+public class ServeControllerTest extends MockMvcConfigBase {
+    @Spy
+    private static Serve serve1;
+    private static Serve serve2;
+    @MockBean
+    private ServeService service;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @BeforeAll
+    static void beforeAll() {
+        serve1 = ServeBuilder.aServe().name("Serve 1").identifier("Description 1").build();
+        serve1.setId(1L);
+        serve2 = ServeBuilder.aServe().name("Serve 2").identifier("Description 2").build();
+        serve2.setId(2L);
+    }
+
+    @Test
+    void create() throws Exception {
+        ServeDto dto = new ServeDto();
+        dto.setProductId(121L);
+        dto.setName(serve1.getName());
+        dto.setIdentifier(serve1.getIdentifier());
+        dto.setInputs(null);
+        dto.setOutputs(null);
+        when(service.create(any(ServeDto.class))).thenReturn(serve1);
+        mockMvc.perform(post("/api/rest/tsl/serve")
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).create(any(ServeDto.class));
+    }
+
+    @Test
+    void list() throws Exception {
+        List<Serve> serves = Lists.newArrayList(serve1, serve2);
+        when(service.page(any(Page.class), any(LambdaQueryWrapper.class))).thenReturn(new Page<Serve>().setRecords(serves).setTotal((long) serves.size()));
+        mockMvc.perform(get("/api/rest/tsl/serve").with(user(userDetails)))
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).page(any(Page.class), any(LambdaQueryWrapper.class));
+    }
+
+    @Test
+    void update() throws Exception {
+        ServeDto dto = new ServeDto();
+        dto.setProductId(121L);
+        dto.setName(serve1.getName());
+        dto.setIdentifier(serve1.getIdentifier());
+        dto.setInputs(null);
+        dto.setOutputs(null);
+        when(service.update(any(ServeDto.class), anyLong())).thenReturn(serve1);
+        mockMvc.perform(patch("/api/rest/tsl/serve/{id}", serve1.getId())
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).update(any(ServeDto.class), anyLong());
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/rest/notice/BulletinControllerTest.java b/src/test/java/com/zsc/edu/gateway/rest/notice/BulletinControllerTest.java
index 92da100..6ac6c16 100644
--- a/src/test/java/com/zsc/edu/gateway/rest/notice/BulletinControllerTest.java
+++ b/src/test/java/com/zsc/edu/gateway/rest/notice/BulletinControllerTest.java
@@ -1,12 +1,14 @@
 package com.zsc.edu.gateway.rest.notice;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zsc.edu.gateway.MockMvcConfigBase;
 import com.zsc.edu.gateway.domain.notice.BulletinBuilder;
 import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
+import com.zsc.edu.gateway.modules.notice.controller.BulletinController;
 import com.zsc.edu.gateway.modules.notice.dto.BulletinDto;
 import com.zsc.edu.gateway.modules.notice.entity.Bulletin;
 import com.zsc.edu.gateway.modules.notice.service.BulletinService;
-import com.zsc.edu.gateway.modules.system.controller.AuthorityController;
 import org.assertj.core.util.Lists;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -27,7 +29,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
 import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
-@WebMvcTest(AuthorityController.class)
+@WebMvcTest(BulletinController.class)
 public class BulletinControllerTest extends MockMvcConfigBase {
     @Spy
     private static Bulletin bulletin1;
@@ -66,7 +68,7 @@ public class BulletinControllerTest extends MockMvcConfigBase {
         when(service.list()).thenReturn(bulletins);
         mockMvc.perform(get("/api/rest/bulletin").with(user(userDetails))
         ).andExpect(status().isOk()).andDo(print());
-        verify(service).list();
+        verify(service).page(any(Page.class), any(LambdaQueryWrapper.class));
     }
 
     @Test
diff --git a/src/test/java/com/zsc/edu/gateway/rest/notice/UserMessageControllerTest.java b/src/test/java/com/zsc/edu/gateway/rest/notice/UserMessageControllerTest.java
new file mode 100644
index 0000000..d614b60
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/rest/notice/UserMessageControllerTest.java
@@ -0,0 +1,78 @@
+package com.zsc.edu.gateway.rest.notice;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zsc.edu.gateway.MockMvcConfigBase;
+import com.zsc.edu.gateway.domain.notice.UserMessageBuilder;
+import com.zsc.edu.gateway.modules.notice.controller.UserMessageController;
+import com.zsc.edu.gateway.modules.notice.dto.UserMessageDto;
+import com.zsc.edu.gateway.modules.notice.entity.MessageType;
+import com.zsc.edu.gateway.modules.notice.entity.UserMessage;
+import com.zsc.edu.gateway.modules.notice.query.AdminMessageQuery;
+import com.zsc.edu.gateway.modules.notice.service.UserMessageService;
+import org.assertj.core.util.Lists;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Spy;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@WebMvcTest(UserMessageController.class)
+public class UserMessageControllerTest extends MockMvcConfigBase {
+    @Spy
+    private static UserMessage userMessage1;
+    private static UserMessage userMessage2;
+    @MockBean
+    private UserMessageService service;
+
+    @BeforeAll
+    static void beforeAll() {
+        userMessage1 = UserMessageBuilder.builder().setMessageId(1L).setUserId(1L).setIsRead(true).build();
+        userMessage2 = UserMessageBuilder.builder().setMessageId(1L).setUserId(1L).setIsRead(false).build();
+    }
+
+    @Test
+    void list() throws Exception {
+        List<UserMessage> userMessages = Lists.newArrayList(userMessage1, userMessage2);
+        Page<UserMessage> pageResult = new Page<>();
+        pageResult.setRecords(userMessages);
+        pageResult.setTotal((long) userMessages.size());
+        when(service.getAdminMessagePage(any(Page.class), any(AdminMessageQuery.class))).thenReturn(pageResult);
+        mockMvc.perform(get("/api/rest/message")
+                        .with(user(userDetails))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).getAdminMessagePage(any(Page.class), any(AdminMessageQuery.class));
+    }
+
+    @Test
+    void create() throws Exception {
+        UserMessageDto dto = new UserMessageDto();
+        dto.setTitle("测试创建消息");
+        dto.setContent("测试创建消息");
+        dto.setType(MessageType.other);
+        when(service.createByAdmin(any(UserMessageDto.class))).thenReturn(true);
+        mockMvc.perform(post("/api/rest/message")
+                        .with(csrf().asHeader())
+                        .with(user(userDetails))
+                        .contentType(MediaType.APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(dto))
+                )
+                .andExpect(status().isOk())
+                .andDo(print());
+        verify(service).createByAdmin(any(UserMessageDto.class));
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/service/iot/EventServiceTest.java b/src/test/java/com/zsc/edu/gateway/service/iot/EventServiceTest.java
new file mode 100644
index 0000000..a947730
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/service/iot/EventServiceTest.java
@@ -0,0 +1,101 @@
+package com.zsc.edu.gateway.service.iot;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.zsc.edu.gateway.domain.iot.EventBuilder;
+import com.zsc.edu.gateway.domain.iot.ServeBuilder;
+import com.zsc.edu.gateway.exception.ConstraintException;
+import com.zsc.edu.gateway.modules.iot.tsl.dto.ParamDto;
+import com.zsc.edu.gateway.modules.iot.tsl.dto.EventDto;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.DataType;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Event;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Event;
+import com.zsc.edu.gateway.modules.iot.tsl.repo.EventRepository;
+import com.zsc.edu.gateway.modules.iot.tsl.repo.ParamRepository;
+import com.zsc.edu.gateway.modules.iot.tsl.service.EventService;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@SpringBootTest
+public class EventServiceTest {
+    @Autowired
+    private EventService service;
+    @Autowired
+    private EventRepository repo;
+    @Autowired
+    private ParamRepository paramRepo;
+
+    private Event event1;
+    private Event event2;
+
+    @BeforeEach
+    void setUp() {
+        event1 = EventBuilder.builder().setName("EVENT_NAME_1").setIdentifier("测试1").setProductId(121L).setType(Event.Type.ACTIVE).build();
+        repo.insert(event1);
+        event2 = EventBuilder.builder().setName("EVENT_NAME_2").setIdentifier("测试2").setProductId(121L).setType(Event.Type.ACTIVE).build();
+        repo.insert(event2);
+    }
+
+    @AfterEach
+    void tearDown() {
+        repo.delete(new LambdaQueryWrapper<Event>()
+                .in(Event::getName, "EVENT_NAME_1", "EVENT_NAME_2", "EVENT_3", "EVENT_UPDATE"));
+        paramRepo.delete(new LambdaQueryWrapper<Param>()
+                .in(Param::getName, "联合测试1"));
+    }
+
+    @Test
+    void list() {
+        LambdaQueryWrapper<Event> queryWrapper = new LambdaQueryWrapper<>();
+        assertEquals(2, service.list(queryWrapper.like(Event::getName, "EVENT")).size());
+        assertEquals(1, service.list(queryWrapper.eq(Event::getName, event1.getName())).size());
+//        assertEquals(2, service.list().size());
+    }
+
+    @Test
+    void createProduct() {
+        EventDto dto = new EventDto(121L, "EVENT_3", "测试3", Event.Type.ACTIVE, createParam());
+        Event Event = service.create(dto);
+        assertNotNull(Event);
+        List<Event> events = service.list(new QueryWrapper<Event>().like("name", "EVENT"));
+        assertEquals(3, events.size());
+        // 不能创建其他已存在的同名同代码部门
+        EventDto dto2 = new EventDto(121L, event2.getName(), "测试1", null, null);
+        assertThrows(ConstraintException.class, () -> service.create(dto2));
+    }
+
+    @Test
+    void updateProduct() {
+        EventDto dto = new EventDto();
+        dto.setName("EVENT_UPDATE");
+        dto.setIdentifier("测试更新");
+        dto.setProductId(121L);
+        dto.setOutputs(createParam());
+        service.update(dto, event2.getId());
+        Event updatedServe = repo.selectOne(new LambdaQueryWrapper<Event>().eq(Event::getName, dto.getName()));
+        assertNotNull(updatedServe);
+        assertEquals("EVENT_UPDATE", updatedServe.getName());
+        assertEquals(event2.getId(), updatedServe.getId());
+    }
+
+
+    public List<ParamDto> createParam() {
+        ParamDto paramDto = new ParamDto();
+        paramDto.setName("联合测试1");
+        paramDto.setType(Param.Type.OUTPUT);
+        paramDto.setDataType(DataType.DATE);
+        List<ParamDto> params = new ArrayList<>();
+        params.add(paramDto);
+        return params;
+    }
+}
diff --git a/src/test/java/com/zsc/edu/gateway/service/iot/ParamServiceTest.java b/src/test/java/com/zsc/edu/gateway/service/iot/ParamServiceTest.java
index 6338624..9a54570 100644
--- a/src/test/java/com/zsc/edu/gateway/service/iot/ParamServiceTest.java
+++ b/src/test/java/com/zsc/edu/gateway/service/iot/ParamServiceTest.java
@@ -1,9 +1,13 @@
 package com.zsc.edu.gateway.service.iot;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.zsc.edu.gateway.domain.iot.ParamBuilder;
+import com.zsc.edu.gateway.exception.ConstraintException;
+import com.zsc.edu.gateway.modules.iot.tsl.dto.EventDto;
 import com.zsc.edu.gateway.modules.iot.tsl.dto.ParamDto;
 import com.zsc.edu.gateway.modules.iot.tsl.entity.DataType;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Event;
 import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
 import com.zsc.edu.gateway.modules.iot.tsl.repo.ParamRepository;
 import com.zsc.edu.gateway.modules.iot.tsl.service.ParamService;
@@ -12,6 +16,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -20,9 +25,12 @@ import java.util.List;
 import static org.junit.jupiter.api.Assertions.*;
 
 @SpringBootTest
+@Transactional
 public class ParamServiceTest {
+
     @Autowired
     private ParamService service;
+
     @Autowired
     private ParamRepository repo;
 
@@ -31,60 +39,49 @@ public class ParamServiceTest {
 
     @BeforeEach
     void setUp() {
-        param1 = ParamBuilder.aParam().uint("测试1").foreignId(1L).build();
+        param1 = ParamBuilder.aParam().name("PARAM_NAME_1").foreignId(1L).dataType(DataType.DATE).build();
         repo.insert(param1);
-        param2 = ParamBuilder.aParam().uint("测试2").foreignId(2L).build();
+        param2 = ParamBuilder.aParam().name("PARAM_NAME_2").foreignId(2L).dataType(DataType.DATE).build();
         repo.insert(param2);
     }
 
+    @AfterEach
+    void tearDown() {
+        repo.delete(new LambdaQueryWrapper<Param>()
+                .in(Param::getName, "PARAM_NAME_1", "PARAM_NAME_2", "PARAM_NAME_3", "PARAM_UPDATE"));
+    }
+
     @Test
     void list() {
         LambdaQueryWrapper<Param> queryWrapper = new LambdaQueryWrapper<>();
-        assertEquals(2, service.list(queryWrapper.like(Param::getUint, "测试")).size());
-        assertEquals(1, service.list(queryWrapper.eq(Param::getUint, param1.getUint())).size());
-//        assertEquals(2, service.list().size());
+        assertEquals(2, service.list(queryWrapper.like(Param::getName, "PARAM")).size());
+        assertEquals(1, service.list(queryWrapper.eq(Param::getName, param1.getName())).size());
     }
 
     @Test
     void createParams() {
-        List<ParamDto> params = createParamDtoList();
+        ParamDto dto = new ParamDto("PARAM_NAME_3", "测试1", DataType.DATE, Param.Type.OUTPUT);
+        List<ParamDto> params = new ArrayList<>();
+        params.add(dto);
         Long foreignId = 1L;
         Boolean result = service.create(params, foreignId, null);
         assertTrue(result);
-        List<Param> insertedParams = service.list(new LambdaQueryWrapper<Param>().like(Param::getName, "PARAM_NAME"));
-        assertEquals(2, insertedParams.size()); // 因为setUp方法已经插入了两个参数
+        List<Param> insertedParams = service.list(new LambdaQueryWrapper<Param>().like(Param::getName, "PARAM"));
+        assertEquals(3, insertedParams.size());
     }
 
     @Test
     void updateParams() {
         ParamDto dto = new ParamDto();
-        dto.setName("PARAM_NAME_UPDATE");
+        dto.setName("PARAM_UPDATE");
         dto.setIdentifier("测试更新");
         List<ParamDto> params = new ArrayList<>();
         params.add(dto);
         assertTrue(service.update(params, param2.getForeignId()));
-        Param updatedParam = repo.selectOne(new LambdaQueryWrapper<Param>().eq(Param::getForeignId, param2.getForeignId()));
+        Param updatedParam = repo.selectOne(new LambdaQueryWrapper<Param>().eq(Param::getName, dto.getName()));
         assertNotNull(updatedParam);
-        assertEquals("测试更新", updatedParam.getIdentifier());
+        assertEquals("PARAM_UPDATE", updatedParam.getName());
         assertEquals(param2.getId(), updatedParam.getId());
     }
 
-
-    @AfterEach
-    void tearDown() {
-        repo.delete(new LambdaQueryWrapper<Param>()
-                .in(Param::getName, "PARAM_NAME_1", "PARAM_NAME_2", "PARAM_NAME_UPDATE"));
-    }
-
-    private List<ParamDto> createParamDtoList() {
-        ParamDto paramDto1 = new ParamDto();
-        paramDto1.setName("PARAM_NAME_1");
-        paramDto1.setIdentifier("PARAM_VALUE_1");
-        paramDto1.setDataType(DataType.DATE);
-        ParamDto paramDto2 = new ParamDto();
-        paramDto2.setName("PARAM_NAME_2");
-        paramDto2.setIdentifier("PARAM_VALUE_2");
-        paramDto2.setDataType(DataType.DATE);
-        return Arrays.asList(paramDto1, paramDto2);
-    }
 }
diff --git a/src/test/java/com/zsc/edu/gateway/service/iot/PropertyServiceTest.java b/src/test/java/com/zsc/edu/gateway/service/iot/PropertyServiceTest.java
new file mode 100644
index 0000000..71f67fe
--- /dev/null
+++ b/src/test/java/com/zsc/edu/gateway/service/iot/PropertyServiceTest.java
@@ -0,0 +1,75 @@
+package com.zsc.edu.gateway.service.iot;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zsc.edu.gateway.domain.iot.PropertyBuilder;
+import com.zsc.edu.gateway.modules.iot.tsl.dto.PropertyDto;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.DataType;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Property;
+import com.zsc.edu.gateway.modules.iot.tsl.repo.PropertyRepository;
+import com.zsc.edu.gateway.modules.iot.tsl.service.PropertyService;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest
+public class PropertyServiceTest {
+    @Autowired
+    private PropertyService service;
+    @Autowired
+    private PropertyRepository repo;
+
+    private Property property1;
+    private Property property2;
+
+    @BeforeEach
+    void setUp() {
+        property1 = PropertyBuilder.builder().setName("PROPERTY_NAME_1").setProductId(121L)
+                .setIoType(Property.IoType.READ_WRITE).setDataType(DataType.DATE).build();
+        repo.insert(property1);
+        property2 = PropertyBuilder.builder().setName("PROPERTY_NAME_2").setProductId(121L)
+                .setIoType(Property.IoType.READ_WRITE).setDataType(DataType.DATE).build();
+        repo.insert(property2);
+    }
+
+    @AfterEach
+    void tearDown() {
+        repo.delete(new LambdaQueryWrapper<Property>()
+                .in(Property::getName, "PROPERTY_NAME_1", "PROPERTY_NAME_2", "PROPERTY_3", "PROPERTY_UPDATE"));
+    }
+
+    @Test
+    void list() {
+        LambdaQueryWrapper<Property> queryWrapper = new LambdaQueryWrapper<>();
+        assertEquals(2, service.list(queryWrapper.like(Property::getName, "PROPERTY")).size());
+        assertEquals(1, service.list(queryWrapper.eq(Property::getName, property1.getName())).size());
+//        assertEquals(2, service.list().size());
+    }
+
+    @Test
+    void createProduct() {
+        PropertyDto dto = new PropertyDto(121L, "PROPERTY_3", "测试3", null, null);
+        Property property = service.create(dto);
+        assertNotNull(property);
+        List<Property> properties = service.list(new LambdaQueryWrapper<Property>().like(Property::getName, "PROPERTY"));
+        assertEquals(3, properties.size());
+    }
+
+    @Test
+    void updateProduct() {
+        PropertyDto dto = new PropertyDto();
+        dto.setName("PROPERTY_UPDATE");
+        dto.setIdentifier("测试更新");
+        dto.setProductId(121L);
+        service.update(dto, property2.getId());
+        Property updatedProperty = repo.selectOne(new LambdaQueryWrapper<Property>().eq(Property::getName, dto.getName()));
+        assertNotNull(updatedProperty);
+        assertEquals("PROPERTY_UPDATE", updatedProperty.getName());
+        assertEquals(updatedProperty.getId(), updatedProperty.getId());
+    }
+}