Springboot Junit测试说,字段需要类型的豆类; com.labprog.egressos.service.contatoservice'找不到

发布于 2025-02-07 04:12:15 字数 16182 浏览 0 评论 0原文

我完成了Springboot项目的第一个端点类,然后尝试使用@webmvctest和Mock在Junit进行测试。当我运行测试时,由于以下错误,它无法加载ApplicationContext:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field contatoService in com.labprog.egressos.controller.EgressoController required a bean of type 'com.labprog.egressos.service.ContatoService' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)

Action:

Consider defining a bean of type 'com.labprog.egressos.service.ContatoService' in your configuration.

2022-06-12 11:55:30.365 ERROR 23962 --- [           main] o.s.test.context.TestContextManager      : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@7139992f] to prepare test instance [com.labprog.egressos.controller.EgressoControllerTest@3df1a1ac]

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132) ~[spring-test-5.3.19.jar:5.3.19]
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124) ~[spring-test-5.3.19.jar:5.3.19]
    ...

我的项目的文件结构是:

.
├── controller
│   └── EgressoController.java
├── EgressosApplication.java
├── model
│   ├── Cargo.java
│   ├── Contato.java
│   ├── CursoEgresso.java
│   ├── CursoEgressoPK.java
│   ├── Curso.java
│   ├── Depoimento.java
│   ├── dto
│   │   ├── ContatoDTO.java
│   │   └── EgressoDTO.java
│   ├── Egresso.java
│   ├── FaixaSalario.java
│   ├── ProfEgresso.java
│   └── repository
│       ├── CargoRepo.java
│       ├── ContatoRepo.java
│       ├── CursoEgressoRepo.java
│       ├── CursoRepo.java
│       ├── DepoimentoRepo.java
│       ├── EgressoRepo.java
│       ├── FaixaSalarioRepo.java
│       └── ProfEgressoRepo.java
└── service
    ├── CargoService.java
    ├── ContatoService.java
    ├── CursoEgressoService.java
    ├── CursoService.java
    ├── DepoimentoService.java
    ├── EgressoService.java
    ├── exceptions
    │   ├── RegraNegocioRunTime.java
    │   └── ServiceRuntimeException.java
    └── FaixaSalarioService.java

我的egressocontroller.java类:

package com.labprog.egressos.controller;

import java.util.ArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.labprog.egressos.service.ContatoService;
import com.labprog.egressos.service.CursoService;
import com.labprog.egressos.service.EgressoService;
import com.labprog.egressos.service.exceptions.ServiceRuntimeException;
import com.labprog.egressos.model.Contato;
import com.labprog.egressos.model.Egresso;
import com.labprog.egressos.model.dto.ContatoDTO;
import com.labprog.egressos.model.dto.EgressoDTO;

@SuppressWarnings("rawtypes")
@RestController
@RequestMapping("/api/egressos")
public class EgressoController {
    @Autowired
    private EgressoService service;
    
    @Autowired
    private ContatoService contatoService;

    @PostMapping("/salvar")
    public ResponseEntity salvar(@RequestBody EgressoDTO dto) {
        Egresso egresso = Egresso.builder()
                .nome(dto.getNome())
                .email(dto.getEmail())
                .cpf(dto.getCpf())
                .resumo(dto.getResumo())
                .urlFoto(dto.getUrlFoto())
                .build();
        try {
            Egresso salvo = service.salvar(egresso);
            return ResponseEntity.status(HttpStatus.CREATED).body(salvo);
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @PutMapping("/atualizar/{id}")
    public ResponseEntity atualizar(
            @RequestBody EgressoDTO dto,
            @PathVariable Long id) {
        Egresso egresso = Egresso.builder()
                .id(id)
                .nome(dto.getNome())
                .email(dto.getEmail())
                .cpf(dto.getCpf())
                .resumo(dto.getResumo())
                .urlFoto(dto.getUrlFoto())
                .build();
        try {
            Egresso salvo = service.atualizar(egresso);
            return ResponseEntity.status(HttpStatus.OK).body(salvo);
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @PutMapping("/atualizar_contatos/{id}")
    public ResponseEntity atualizarContatos(
            @RequestBody EgressoDTO dto,
            @PathVariable Long id) {
        Egresso egresso = Egresso.builder()
                .id(id)
                .nome(dto.getNome())
                .email(dto.getEmail())
                .cpf(dto.getCpf())
                .resumo(dto.getResumo())
                .urlFoto(dto.getUrlFoto())
                .build();
        ArrayList<Contato> contatos = new ArrayList<>();
        for (ContatoDTO contatoDto : dto.getContatos()) {
            Contato contato = Contato.builder()
                    .id(contatoDto.getId())
                    .nome(contatoDto.getNome())
                    .urlLogo(contatoDto.getUrlLogo())
                    .build();
            contatos.add(contato);
        }
        ArrayList<Contato> contatosValidados = new ArrayList<>();
        try {
            for (Contato contato : contatos) {
                if(contato.getId() == null) {
                    contatosValidados.add(contatoService.salvar(contato));
                } else {
                    contatosValidados.add(contatoService.atualizar(contato));
                }
            }
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
        try {
            Egresso salvo = service.atualizarContatos(egresso, contatosValidados);
            return ResponseEntity.status(HttpStatus.OK).body(salvo);
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @PostMapping("/remover/{id}")
    public ResponseEntity remover(@PathVariable Long id) {
        Egresso egresso = Egresso.builder()
                .id(id)
                .build();
        try {
            service.remover(egresso);
            return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @GetMapping("/buscar/{email}")
    public ResponseEntity buscar(@PathVariable String email) {
        Egresso filtro = Egresso.builder()
                .email(email)
                .build();
        try {
            Egresso egresso = service.buscar(filtro).get(0);
            return ResponseEntity.status(HttpStatus.OK).body(egresso);
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

}

我的contatoservice.java类:

package com.labprog.egressos.service;

import java.util.List;

import com.labprog.egressos.model.Contato;
import com.labprog.egressos.model.repository.ContatoRepo;
import com.labprog.egressos.service.exceptions.ServiceRuntimeException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.ExampleMatcher.StringMatcher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ContatoService {
    
    @Autowired 
    private ContatoRepo repo;

    @Transactional
    public Contato salvar(Contato contato) {
        verificarContato(contato);
        return repo.save(contato);
    }

    @Transactional
    public Contato atualizar(Contato contato) {
        verificarContato(contato);
        verificarId(contato);
        return repo.save(contato);
    }

    @Transactional
    public void remover(Contato contato) {
        verificarId(contato);
        repo.delete(contato);
    }

    public List<Contato> buscar(Contato filtro) {
        Example<Contato> example =
                Example.of(filtro, ExampleMatcher.matching()
                        .withIgnoreCase()
                        .withStringMatcher(StringMatcher.CONTAINING)
                );

        return repo.findAll(example);
    }

    private void verificarContato(Contato contato) {
        if (contato == null)
            throw new ServiceRuntimeException("O contato está nulo");                
        if ((contato.getNome() == null) || (contato.getNome().equals("")))
            throw new ServiceRuntimeException("Nome do contato deve ser informado");                   
    }

    private void verificarId(Contato contato) {
        if ((contato == null) || (contato.getId() == null)) {
            throw new ServiceRuntimeException("ID de contato inválido");
        }
    }

}

我的egressocontrollertest.java class:

package com.labprog.egressos.controller;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.labprog.egressos.model.Egresso;
import com.labprog.egressos.model.dto.EgressoDTO;
import com.labprog.egressos.service.EgressoService;

@ExtendWith(SpringExtension.class)
@WebMvcTest (controllers =  EgressoController.class)
@AutoConfigureMockMvc
public class EgressoControllerTest {
    
    static final String API = "/api/egressos";

    @Autowired
    MockMvc mvc;

    @MockBean
    EgressoService service;

    @Test
    public void deveSalvarEgresso() throws Exception {
        // Cenário
        EgressoDTO dto = EgressoDTO.builder()
                .nome("Nome")
                .email("[email protected]")
                .cpf("123456789")
                .resumo("Resumo")
                .urlFoto("urlFoto")
                .build();

        Egresso egresso = Egresso.builder()
                .id(1l)
                .nome(dto.getNome())
                .email(dto.getEmail())
                .cpf(dto.getCpf())
                .resumo(dto.getResumo())
                .urlFoto(dto.getUrlFoto())
                .build();

        Mockito.when(service.salvar(
            Mockito.any(Egresso.class))).thenReturn(egresso);

        String json = new ObjectMapper().writeValueAsString(dto);

        // Ação
        MockHttpServletRequestBuilder request = 
            MockMvcRequestBuilders.post(API + "/salvar")
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .content(json);

        // Verificação
        mvc.perform(request)
            .andExpect(MockMvcResultMatchers.status().isCreated());
    }

}

and pom.xml:我需要我的pom.xml:我需要我的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.labprog</groupId>
    <artifactId>egressos</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>egressos</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>18</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

我需要我的atualizarcontatos()方法(更新Egresso的联系人列表)的contatoservice实例。奇怪的是,自动弹跳按照预期的方式工作,如果我运行测试评论和测试作品的测试评论。无论我在控制器中包括什么其他服务类,都会产生错误。

它使我感到困惑,好像我运行了应用程序并尝试使用失眠症中的atualizarcontatos()的端点一样,它可以正常工作:

我的服务和模型已经涵盖了测试。为什么控制器不能正确注入依赖项?

我在Ubuntu 20.04.4 LTS工作Java 18。

I made the first endpoint class of my SpringBoot project, then tried to test it with JUnit, using @WebMvcTest and mocks. When I run the test it fails to load ApplicationContext because of the following error:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field contatoService in com.labprog.egressos.controller.EgressoController required a bean of type 'com.labprog.egressos.service.ContatoService' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)

Action:

Consider defining a bean of type 'com.labprog.egressos.service.ContatoService' in your configuration.

2022-06-12 11:55:30.365 ERROR 23962 --- [           main] o.s.test.context.TestContextManager      : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@7139992f] to prepare test instance [com.labprog.egressos.controller.EgressoControllerTest@3df1a1ac]

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132) ~[spring-test-5.3.19.jar:5.3.19]
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124) ~[spring-test-5.3.19.jar:5.3.19]
    ...

My project's file structure is this:

.
├── controller
│   └── EgressoController.java
├── EgressosApplication.java
├── model
│   ├── Cargo.java
│   ├── Contato.java
│   ├── CursoEgresso.java
│   ├── CursoEgressoPK.java
│   ├── Curso.java
│   ├── Depoimento.java
│   ├── dto
│   │   ├── ContatoDTO.java
│   │   └── EgressoDTO.java
│   ├── Egresso.java
│   ├── FaixaSalario.java
│   ├── ProfEgresso.java
│   └── repository
│       ├── CargoRepo.java
│       ├── ContatoRepo.java
│       ├── CursoEgressoRepo.java
│       ├── CursoRepo.java
│       ├── DepoimentoRepo.java
│       ├── EgressoRepo.java
│       ├── FaixaSalarioRepo.java
│       └── ProfEgressoRepo.java
└── service
    ├── CargoService.java
    ├── ContatoService.java
    ├── CursoEgressoService.java
    ├── CursoService.java
    ├── DepoimentoService.java
    ├── EgressoService.java
    ├── exceptions
    │   ├── RegraNegocioRunTime.java
    │   └── ServiceRuntimeException.java
    └── FaixaSalarioService.java

My EgressoController.java class:

package com.labprog.egressos.controller;

import java.util.ArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.labprog.egressos.service.ContatoService;
import com.labprog.egressos.service.CursoService;
import com.labprog.egressos.service.EgressoService;
import com.labprog.egressos.service.exceptions.ServiceRuntimeException;
import com.labprog.egressos.model.Contato;
import com.labprog.egressos.model.Egresso;
import com.labprog.egressos.model.dto.ContatoDTO;
import com.labprog.egressos.model.dto.EgressoDTO;

@SuppressWarnings("rawtypes")
@RestController
@RequestMapping("/api/egressos")
public class EgressoController {
    @Autowired
    private EgressoService service;
    
    @Autowired
    private ContatoService contatoService;

    @PostMapping("/salvar")
    public ResponseEntity salvar(@RequestBody EgressoDTO dto) {
        Egresso egresso = Egresso.builder()
                .nome(dto.getNome())
                .email(dto.getEmail())
                .cpf(dto.getCpf())
                .resumo(dto.getResumo())
                .urlFoto(dto.getUrlFoto())
                .build();
        try {
            Egresso salvo = service.salvar(egresso);
            return ResponseEntity.status(HttpStatus.CREATED).body(salvo);
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @PutMapping("/atualizar/{id}")
    public ResponseEntity atualizar(
            @RequestBody EgressoDTO dto,
            @PathVariable Long id) {
        Egresso egresso = Egresso.builder()
                .id(id)
                .nome(dto.getNome())
                .email(dto.getEmail())
                .cpf(dto.getCpf())
                .resumo(dto.getResumo())
                .urlFoto(dto.getUrlFoto())
                .build();
        try {
            Egresso salvo = service.atualizar(egresso);
            return ResponseEntity.status(HttpStatus.OK).body(salvo);
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @PutMapping("/atualizar_contatos/{id}")
    public ResponseEntity atualizarContatos(
            @RequestBody EgressoDTO dto,
            @PathVariable Long id) {
        Egresso egresso = Egresso.builder()
                .id(id)
                .nome(dto.getNome())
                .email(dto.getEmail())
                .cpf(dto.getCpf())
                .resumo(dto.getResumo())
                .urlFoto(dto.getUrlFoto())
                .build();
        ArrayList<Contato> contatos = new ArrayList<>();
        for (ContatoDTO contatoDto : dto.getContatos()) {
            Contato contato = Contato.builder()
                    .id(contatoDto.getId())
                    .nome(contatoDto.getNome())
                    .urlLogo(contatoDto.getUrlLogo())
                    .build();
            contatos.add(contato);
        }
        ArrayList<Contato> contatosValidados = new ArrayList<>();
        try {
            for (Contato contato : contatos) {
                if(contato.getId() == null) {
                    contatosValidados.add(contatoService.salvar(contato));
                } else {
                    contatosValidados.add(contatoService.atualizar(contato));
                }
            }
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
        try {
            Egresso salvo = service.atualizarContatos(egresso, contatosValidados);
            return ResponseEntity.status(HttpStatus.OK).body(salvo);
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @PostMapping("/remover/{id}")
    public ResponseEntity remover(@PathVariable Long id) {
        Egresso egresso = Egresso.builder()
                .id(id)
                .build();
        try {
            service.remover(egresso);
            return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @GetMapping("/buscar/{email}")
    public ResponseEntity buscar(@PathVariable String email) {
        Egresso filtro = Egresso.builder()
                .email(email)
                .build();
        try {
            Egresso egresso = service.buscar(filtro).get(0);
            return ResponseEntity.status(HttpStatus.OK).body(egresso);
        } catch (ServiceRuntimeException e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

}

My ContatoService.java class:

package com.labprog.egressos.service;

import java.util.List;

import com.labprog.egressos.model.Contato;
import com.labprog.egressos.model.repository.ContatoRepo;
import com.labprog.egressos.service.exceptions.ServiceRuntimeException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.ExampleMatcher.StringMatcher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ContatoService {
    
    @Autowired 
    private ContatoRepo repo;

    @Transactional
    public Contato salvar(Contato contato) {
        verificarContato(contato);
        return repo.save(contato);
    }

    @Transactional
    public Contato atualizar(Contato contato) {
        verificarContato(contato);
        verificarId(contato);
        return repo.save(contato);
    }

    @Transactional
    public void remover(Contato contato) {
        verificarId(contato);
        repo.delete(contato);
    }

    public List<Contato> buscar(Contato filtro) {
        Example<Contato> example =
                Example.of(filtro, ExampleMatcher.matching()
                        .withIgnoreCase()
                        .withStringMatcher(StringMatcher.CONTAINING)
                );

        return repo.findAll(example);
    }

    private void verificarContato(Contato contato) {
        if (contato == null)
            throw new ServiceRuntimeException("O contato está nulo");                
        if ((contato.getNome() == null) || (contato.getNome().equals("")))
            throw new ServiceRuntimeException("Nome do contato deve ser informado");                   
    }

    private void verificarId(Contato contato) {
        if ((contato == null) || (contato.getId() == null)) {
            throw new ServiceRuntimeException("ID de contato inválido");
        }
    }

}

My EgressoControllerTest.java class:

package com.labprog.egressos.controller;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.labprog.egressos.model.Egresso;
import com.labprog.egressos.model.dto.EgressoDTO;
import com.labprog.egressos.service.EgressoService;

@ExtendWith(SpringExtension.class)
@WebMvcTest (controllers =  EgressoController.class)
@AutoConfigureMockMvc
public class EgressoControllerTest {
    
    static final String API = "/api/egressos";

    @Autowired
    MockMvc mvc;

    @MockBean
    EgressoService service;

    @Test
    public void deveSalvarEgresso() throws Exception {
        // Cenário
        EgressoDTO dto = EgressoDTO.builder()
                .nome("Nome")
                .email("[email protected]")
                .cpf("123456789")
                .resumo("Resumo")
                .urlFoto("urlFoto")
                .build();

        Egresso egresso = Egresso.builder()
                .id(1l)
                .nome(dto.getNome())
                .email(dto.getEmail())
                .cpf(dto.getCpf())
                .resumo(dto.getResumo())
                .urlFoto(dto.getUrlFoto())
                .build();

        Mockito.when(service.salvar(
            Mockito.any(Egresso.class))).thenReturn(egresso);

        String json = new ObjectMapper().writeValueAsString(dto);

        // Ação
        MockHttpServletRequestBuilder request = 
            MockMvcRequestBuilders.post(API + "/salvar")
            .accept(MediaType.APPLICATION_JSON)
            .contentType(MediaType.APPLICATION_JSON)
            .content(json);

        // Verificação
        mvc.perform(request)
            .andExpect(MockMvcResultMatchers.status().isCreated());
    }

}

And my pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.labprog</groupId>
    <artifactId>egressos</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>egressos</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>18</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

I need the ContatoService instance for my atualizarContatos() method (update Egresso's list of Contact). It's odd that the autowired EgressoService works as supposed, and if I run the test commenting contatoService and atualizarContatos(), the test works. Whatever other service class I include as @Autowired in my controller, it yields that error.

It confuses me, as if I run the application and try to use the endpoint for atualizarContatos() in Insomnia, it works just fine:
Insomnia using the endpoint atualizarContatos()

My services and models are covered with tests already. Why can't the controller test inject the dependencies correctly?

I'm working in Ubuntu 20.04.4 LTS with Java 18.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

赏烟花じ飞满天 2025-02-14 04:12:15

我在API网关单元测试中遇到了同样的问题。

对我有用的是将bean添加到单元测试中:

@MockBean
private AuthRestClient mockClient;

完整:


here are my imports etc:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import com.xxx.yyyy.core.interfaces.constants.AuthorityConstants;
import com.xxx.yyy.core.interfaces.ws.AuthRestClient;


@ExtendWith(SpringExtension.class)
@SpringBootTest
@ActiveProfiles(value = "test")
@WithMockUser(username = "admin", roles = { AuthorityConstants.PRIV_USERADMIN })
class XxxServicesApiGatewayApplicationTests {

    @MockBean
    private AuthRestClient mockClient;

    @Test
    void test() {

        // assertions, etc.
    }
}

I had the same problem in our API Gateway unit tests.

what worked for me is adding the bean to the unit test as:

@MockBean
private AuthRestClient mockClient;

full:


here are my imports etc:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import com.xxx.yyyy.core.interfaces.constants.AuthorityConstants;
import com.xxx.yyy.core.interfaces.ws.AuthRestClient;


@ExtendWith(SpringExtension.class)
@SpringBootTest
@ActiveProfiles(value = "test")
@WithMockUser(username = "admin", roles = { AuthorityConstants.PRIV_USERADMIN })
class XxxServicesApiGatewayApplicationTests {

    @MockBean
    private AuthRestClient mockClient;

    @Test
    void test() {

        // assertions, etc.
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文