使用 postman 返回的错误请求但未在单元测试中返回 spring 启动
bad request returned using postman but not in unit testing spring boot
我有一个带有唯一字段“名称”的类别实体。
我正在使用自定义唯一注释来验证数据并且它工作得很好。
我正在尝试在我的 spring 引导应用程序上测试我的控制器,如果数据重复(唯一名称),我想检查请求 returns 是否为 400 状态。
在邮递员中它按预期工作,returns 400 状态和错误列表。
通过单元测试,它 returns 一个带有空主体的 201 状态(但实际上,返回 201 意味着主体包含新创建的实体!)
这是我的测试:
@Test
public void testIfAdminCanCreateCategory_expect400BecauseCategoryAlreadyExist() throws Exception {
// json
String data = "{\"name\" : \"CATEGORY\"}";
mockMvc().with(keycloakAuthenticationToken().authorities("ROLE_admin")).perform(post("/categories").content(data).contentType("application/json"))
.andDo(print())
.andDo(r -> mockMvc().with(keycloakAuthenticationToken().authorities("ROLE_admin"))
.perform(post("/categories").content(data).contentType("application/json"))
.andExpect(status().isBadRequest()));
}
我的控制器:
@PostMapping
@PreAuthorize("hasRole('ROLE_admin')")
public HttpEntity<MainCategory> create(@Valid @RequestBody CreateMainCategory createMainCategory)
{
return ResponseEntity.status(HttpStatus.CREATED).body(mainCategoryService.create(createMainCategory));
}
我的服务:
@Override
public MainCategory create(CreateMainCategory createMainCategory) {
MainCategory mainCategory = new MainCategory();
mainCategory.setName(createMainCategory.getName().toUpperCase());
return mainCategoryRepository.save(mainCategory);
}
我的实体:
@Entity
@EntityListeners( AuditingEntityListener.class )
@Data
public class MainCategory {
@Id @GeneratedValue private Long id;
private String name;
@CreatedBy
private String createdBy;
@OneToMany(cascade = CascadeType.REMOVE, mappedBy = "mainCategory")
List<Category> categories;
}
来自日志的请求:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /categories
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"21"]
Body = {"name" : "CATEGORY"}
Session Attrs = {SPRING_SECURITY_CONTEXT=org.springframework.security.core.context.SecurityContextImpl@6989924: Authentication: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@6989924: Principal: user; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@40fd518f; Granted Authorities: ROLE_admin}
来自日志的响应:
MockHttpServletResponse:
Status = 201
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :400
Actual :201
在测试用例中,没有任何地方显示数据重复。您在测试用例中定义 String 数据并在那里使用它。因此它给出了 200 个创建状态。
在实体创建中,名称未定义为唯一。
@Column(unique=true)
private String name;
默认为假。
问题与 save() 方法有关,即使在我的属性文件上定义 mysql 数据库时它也没有保存任何实体(这解释了 201 创建状态中的空主体)。
一个解决方案是使用 H2 数据库进行测试,将其配置添加到单独的属性文件中(在我的例子中是 product-service-test.yml )并将 @ActiveProfiles("test")
添加到测试 class.
我有一个带有唯一字段“名称”的类别实体。
我正在使用自定义唯一注释来验证数据并且它工作得很好。
我正在尝试在我的 spring 引导应用程序上测试我的控制器,如果数据重复(唯一名称),我想检查请求 returns 是否为 400 状态。
在邮递员中它按预期工作,returns 400 状态和错误列表。
通过单元测试,它 returns 一个带有空主体的 201 状态(但实际上,返回 201 意味着主体包含新创建的实体!)
这是我的测试:
@Test
public void testIfAdminCanCreateCategory_expect400BecauseCategoryAlreadyExist() throws Exception {
// json
String data = "{\"name\" : \"CATEGORY\"}";
mockMvc().with(keycloakAuthenticationToken().authorities("ROLE_admin")).perform(post("/categories").content(data).contentType("application/json"))
.andDo(print())
.andDo(r -> mockMvc().with(keycloakAuthenticationToken().authorities("ROLE_admin"))
.perform(post("/categories").content(data).contentType("application/json"))
.andExpect(status().isBadRequest()));
}
我的控制器:
@PostMapping
@PreAuthorize("hasRole('ROLE_admin')")
public HttpEntity<MainCategory> create(@Valid @RequestBody CreateMainCategory createMainCategory)
{
return ResponseEntity.status(HttpStatus.CREATED).body(mainCategoryService.create(createMainCategory));
}
我的服务:
@Override
public MainCategory create(CreateMainCategory createMainCategory) {
MainCategory mainCategory = new MainCategory();
mainCategory.setName(createMainCategory.getName().toUpperCase());
return mainCategoryRepository.save(mainCategory);
}
我的实体:
@Entity
@EntityListeners( AuditingEntityListener.class )
@Data
public class MainCategory {
@Id @GeneratedValue private Long id;
private String name;
@CreatedBy
private String createdBy;
@OneToMany(cascade = CascadeType.REMOVE, mappedBy = "mainCategory")
List<Category> categories;
}
来自日志的请求:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /categories
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"21"]
Body = {"name" : "CATEGORY"}
Session Attrs = {SPRING_SECURITY_CONTEXT=org.springframework.security.core.context.SecurityContextImpl@6989924: Authentication: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@6989924: Principal: user; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@40fd518f; Granted Authorities: ROLE_admin}
来自日志的响应:
MockHttpServletResponse:
Status = 201
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :400
Actual :201
在测试用例中,没有任何地方显示数据重复。您在测试用例中定义 String 数据并在那里使用它。因此它给出了 200 个创建状态。
在实体创建中,名称未定义为唯一。
@Column(unique=true)
private String name;
默认为假。
问题与 save() 方法有关,即使在我的属性文件上定义 mysql 数据库时它也没有保存任何实体(这解释了 201 创建状态中的空主体)。
一个解决方案是使用 H2 数据库进行测试,将其配置添加到单独的属性文件中(在我的例子中是 product-service-test.yml )并将 @ActiveProfiles("test")
添加到测试 class.