如何使用 springboot 和 sonarqube 测试控制器

时间:2021-04-27 15:05:11

标签: spring-boot controller sonarqube spring-test spring-test-mvc

所以我正在做我的第一个 Spring Boot 项目,但我的测试被困住了。 我查了很多例子,但似乎没有一个有效。

这是我的控制器的当前测试:

@SpringBootTest
@AutoConfigureMockMvc

public class AddPartyTest {


    @Autowired
    private MockMvc mockMvc;

    @Test
    @DisplayName("Should Not give access to endpoint")
    public void ShouldNotGiveAccess() throws Exception{
        mockMvc.perform(MockMvcRequestBuilders.get("/parties"))
                .andExpect(MockMvcResultMatchers.status().is(401));
    }

它可以工作,但是在 sonarqube 上,我发现我的代码覆盖率为 0%,而且我似乎找不到一个测试,甚至可以使这个百分比高于零。 谁能给我一个关于如何为控制器编写好的单元测试的例子,然后我可以根据你的例子自己弄清楚。

这是我的控制器:

@RestController
@RequestMapping("/parties")
public class PartyController {
    @Autowired
    PartyService partyService;

    @GetMapping("")
    public List<Party> list(){
        return partyService.listAllParties();
    }
    @GetMapping("/{id}")
    public ResponseEntity<PartyDto> get(@PathVariable Integer id){
        try{
            PartyDto partyDto = partyService.getParty(id);
            return new ResponseEntity<>(partyDto, HttpStatus.OK);
        } catch (NoSuchElementException e){
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }
    @PostMapping("/")
    public void add(@RequestBody PartyDto partyDto) throws ParseException {
        partyService.saveParty(partyDto);
    }
    @PutMapping("/{id}")
    public ResponseEntity<?> update(@RequestBody PartyDto partyDto, @PathVariable Integer id){
        try{
            PartyDto existParty = partyService.getParty(id);
            partyDto.setId(id);
            partyService.saveParty(partyDto);
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (NoSuchElementException e){
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Integer id){
        partyService.deleteParty(id);
    }

    @DeleteMapping("/")
    public ResponseEntity<HttpStatus> deleteAllParties() {
        try {
            partyService.deleteAll();
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }

    }

}

这是我的服务(以防万一):

@Service
@Transactional
public class PartyService {

    @Autowired
    private PartyRepository partyRepository;
    @Autowired
    private ModelMapper modelMapper;
    public List<Party> listAllParties() {
        return partyRepository.findAll();
    }

    public void saveParty(PartyDto partyDto){
        Party party = convertToEntity(partyDto);
        partyRepository.save(party);
    }

    public PartyDto getParty(Integer id) {
        Party party = partyRepository.findById(id).orElse(null);
        return convertToDto(party);
    }


    public void deleteParty(Integer id) {
        partyRepository.deleteById(id);
    }
    public void deleteAll() {partyRepository.deleteAll();}

    private PartyDto convertToDto(Party party) {
        PartyDto partyDto = modelMapper.map(party, PartyDto.class);
        return partyDto;
    }
    private Party convertToEntity(PartyDto partyDto) {
        Party entity = new Party();
        entity.setId(partyDto.getId());
        entity.setName(partyDto.getName());
        entity.setDescription(partyDto.getDescription());
        entity.setIspartynational(partyDto.getIspartynational());
        entity.setPartyLeader(partyDto.getPartyLeader());

        return entity;
    }

    }

还有我的党 DTO

@Getter
@Setter
public class PartyDto {
    private Integer id;
    private String name;
    private String description;
    private Boolean ispartynational;
    private PartyLeader partyLeader;

}

我的 build.gradle

plugins {
    id 'org.springframework.boot' version '2.4.2'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
    id "org.sonarqube" version "3.0"
    id 'jacoco'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '15'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation('io.jsonwebtoken:jjwt:0.2')
    implementation 'org.springframework.boot:spring-boot-starter-mail'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compile 'junit:junit:4.12'
    implementation 'org.modelmapper:modelmapper:2.4.1'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    /**
     * JUnit jupiter with mockito.
     */
    testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: '2.19.0'

    /**
     * Mockito for mocking.
     */
    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.19.0'
}

test {
    useJUnitPlatform()
}

如果您需要我的派对模型或存储库,请发表评论,我会添加它们! 提前致谢!

1 个答案:

答案 0 :(得分:0)

现有测试验证匿名用户是否收到 HTTP 401 响应。 MockMvc 请求没有到达控制器,因为 Spring Security 之前阻止了它。因此,您的测试中不会执行任何代码行,这就是您看不到任何覆盖率的原因。

在测试您的 @Controller 类时,请查看 @WebMvcTestMockMvc,它是 great integration with Spring Security 来模拟经过身份验证的用户:

@Test
@WithMockUser("someUsername")
public void shouldAccessPartiesEndpoint() throws Exception {
  this.mockMvc
    .perform(delete("/parties"))
    .andExpect(status().isOk());
}

对于您的 PartyService,使用 Mockito 和 JUnit 进行单元测试就足够了。

如果您想在没有任何模拟的情况下编写 an integration test,请使用 @SpringBootTest 和例如使用 TestRestTemplateWebTestClient 而不是 MockMvc 访问您的应用程序(使用模拟 servlet 环境)。