【问题标题】:@Mock results in exception but @MockBean works in spring boot application@Mock 导致异常但@MockBean 在 spring boot 应用程序中工作
【发布时间】:2023-01-19 05:08:56
【问题描述】:

我正在学习在 spring boot 应用程序中为控制器层编写测试用例。我已经使用@Mock 来模拟服务层测试用例中的存储库接口并且它工作/编译并执行了测试用例。在控制器层测试用例中,@Mock 导致异常,但 @MockBean 有效。

我试图从其他资源中了解 @Mock 和 @MockBean 之间的区别,但希望更清楚地了解为什么 @Mock 在服务测试中有效但在控制器测试中无效。

请参考我的代码 -

  1. 实体

    package com.learning.microservices.userservice.model;
    
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.mongodb.core.mapping.Document;
    
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Document(collection = "Consumer")
    public class Consumer {
        @Id
        private Long consumerId;
        private String consumerName;
        private String emailAddress;
    }
    
  2. 资料库

    package com.learning.microservices.userservice.repository;
    
    import com.learning.microservices.userservice.model.Consumer;
    import org.springframework.data.mongodb.repository.MongoRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface ConsumerRepository extends MongoRepository<Consumer, Long> {
    }
    
  3. 服务

    1. 界面

      package com.learning.microservices.userservice.Service;
      
      import com.learning.microservices.userservice.model.Consumer;
      
      public interface ConsumerService {
          public Consumer saveConsumer(Consumer consumer);
      }
      
    2. 执行

      package com.learning.microservices.userservice.Service;
      
      import com.learning.microservices.userservice.model.Consumer;
      import com.learning.microservices.userservice.repository.ConsumerRepository;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      @Service
      public class ConsumerServiceImpl implements ConsumerService {
          @Autowired
          ConsumerRepository consumerRepository;
      
          public Consumer saveConsumer(Consumer consumer){
              if (consumerRepository.findById(consumer.getConsumerId()).isPresent())
                  throw new RuntimeException("Consumer already exists");//should return 409
              return consumerRepository.save(consumer);
          }
      }
      
    3. 控制器

      package com.learning.microservices.userservice.controller;
      
      import com.learning.microservices.userservice.Service.ConsumerService;
      import com.learning.microservices.userservice.model.Consumer;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.http.ResponseEntity;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RequestBody;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
      
      import java.net.URI;
      
      @RestController
      @RequestMapping("/consumers")
      public class ConsumerController {
      
          @Autowired
          ConsumerService consumerService;
      
          @PostMapping
          public ResponseEntity<Consumer> saveConsumer(@RequestBody Consumer consumer) {
              Consumer savedConsumer = consumerService.saveConsumer(consumer);
              URI consumerLocation = ServletUriComponentsBuilder.fromCurrentRequest().path("/{consumerId}").buildAndExpand(savedConsumer.getConsumerId()).toUri();
              return ResponseEntity.created(consumerLocation).build();
          }
      
      }
      
    4. 测试用例

      1. 服务

        package com.learning.microservices.userservice.Service;
        
        import com.learning.microservices.userservice.model.Consumer;
        import com.learning.microservices.userservice.repository.ConsumerRepository;
        import org.junit.jupiter.api.AfterEach;
        import org.junit.jupiter.api.BeforeEach;
        import org.junit.jupiter.api.Test;
        import org.junit.jupiter.api.extension.ExtendWith;
        import org.mockito.InjectMocks;
        import org.mockito.Mock;
        import org.mockito.junit.jupiter.MockitoExtension;
        
        import java.util.Optional;
        
        import static org.assertj.core.api.Assertions.assertThat;
        import static org.mockito.BDDMockito.given;
        
        @ExtendWith(MockitoExtension.class)
        class ConsumerServiceImplTest {
        
            @Mock
            private ConsumerRepository consumerRepository;
        
            @InjectMocks
            private ConsumerServiceImpl consumerService;
        
            private Consumer consumer;
        
            @BeforeEach
            public void setUp() {
                consumer = Consumer.builder()
                        .consumerId(1L)
                        .consumerName("Test Consumer")
                        .emailAddress("test.consumer@test.com")
                        .build();
            }
        
            @AfterEach
            public void tearDown() {
                consumer = null;
            }
            @Test
            void saveConsumer() {
                given(consumerRepository.findById(consumer.getConsumerId())).willReturn(Optional.empty());
                given(consumerService.saveConsumer(consumer)).willReturn(consumer);
                Consumer savedConsumer = consumerService.saveConsumer(consumer);
                assertThat(savedConsumer).isNotNull();
            }
        
        }
        
      2. 控制器

        package com.learning.microservices.userservice.controller;
        
        import com.fasterxml.jackson.databind.ObjectMapper;
        import com.learning.microservices.userservice.Service.ConsumerServiceImpl;
        import com.learning.microservices.userservice.model.Consumer;
        import org.junit.jupiter.api.AfterEach;
        import org.junit.jupiter.api.BeforeEach;
        import org.junit.jupiter.api.Test;
        import org.mockito.InjectMocks;
        import org.mockito.Mock;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
        import org.springframework.http.MediaType;
        import org.springframework.test.web.servlet.MockMvc;
        import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
        import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
        
        import java.nio.charset.StandardCharsets;
        
        import static org.mockito.BDDMockito.given;
        
        @WebMvcTest
        class ConsumerControllerTest {
        
            private ObjectMapper objectMapper;
            private Consumer consumer;
        
            @Autowired
            private MockMvc mockMvc;
        
            @Mock
            private ConsumerServiceImpl consumerService;
        
            @InjectMocks
            private ConsumerController consumerController;
        
        
            @BeforeEach
            public void setUp() {
                consumer = Consumer.builder()
                        .consumerId(1L)
                        .consumerName("Test Consumer")
                        .emailAddress("test.consumer@test.com")
                        .build();
                objectMapper = new ObjectMapper();
            }
        
            @AfterEach
            public void tearDown() {
                consumer = null;
                objectMapper = null;
            }
        
            @Test
            void saveConsumer() throws Exception {
                given(consumerService.saveConsumer(consumer)).willReturn(consumer);
                mockMvc.perform(MockMvcRequestBuilders.post("/consumers")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(consumer))
                        .characterEncoding(StandardCharsets.UTF_8)
                )
                .andExpect(MockMvcResultMatchers.status().isCreated());
            }
        }
        
      3. 异常日志

        java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@5f8a02cf testClass = com.learning.microservices.userservice.controller.ConsumerControllerTest, locations = [], classes = [com.learning.microservices.userservice.UserServiceApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceLocations = [], propertySourceProperties = ["org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper=true"], contextCustomizers = [[ImportsContextCustomizer@26d5a317 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration, org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration, org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration, org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration, org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration, org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration, org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration, org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration, org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration, org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration, org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityConfiguration, org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@2034b64c, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@7161d8d1, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@d737b89, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@9da1, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@234914f5, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@e322556a, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@2ab4bc72, org.springframework.boot.test.context.SpringBootTestAnnotation@4ddbcfe0], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
        
          at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:142)
          at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:127)
          at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:141)
          at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:97)
          at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:241)
          at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138)
          at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:377)
          at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:382)
          at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:377)
          at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
          at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
          at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
          at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
          at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
          at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
          at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
          at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
          at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
          at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:376)
          at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:289)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:288)
          at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:278)
          at java.base/java.util.Optional.orElseGet(Optional.java:364)
          at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:277)
          at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
          at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:105)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:104)
          at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:68)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
          at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
          at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
          at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
          at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
          at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
          at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
          at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
          at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
          at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
          at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
          at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
          at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
          at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
          at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
          at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
          at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
          at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
          at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
          at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
          at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
          at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
          at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
          at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
          at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
          at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
        Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'consumerController': Unsatisfied dependency expressed through field 'consumerService': No qualifying bean of type 'com.learning.microservices.userservice.Service.ConsumerService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:712)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:692)
          at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:127)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:481)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1397)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
          at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
          at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
          at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:961)
          at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:915)
          at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584)
          at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
          at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432)
          at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
          at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
          at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:59)
          at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:47)
          at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1386)
          at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:543)
          at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
          at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
          at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:184)
          at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:118)
          ... 72 more
        Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.learning.microservices.userservice.Service.ConsumerService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1812)
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1371)
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:709)
          ... 97 more
        

【问题讨论】:

    标签: java spring-boot mockito junit5


    【解决方案1】:

    @Mock@MockBean的区别很简单,就是@MockBean注解了一个对象,注入到Spring上下文中作为测试中的bean使用,也是mock。 @MockBean扩展了@Mock的功能,与Spring框架无关。

    你的Service的测试有与春天无关无论如何-您只需查看该类的导入即可验证这一点。 org.springframework 包中没有一个导入。在这里使用 @Mock 本身就完全没问题。 MockitoExtension@InjectMocks 的组合负责模拟的生命周期。创建模拟实例并将其注入测试对象 (consumerService)。未创建 Spring 上下文。

    Controller 测试的情况下,您使用的是与 Spring 相关的类,尤其是 MockMvc@WebMvcTest - 由于后者,第一个自动注入,@WebMvcTest 设置了用于 Web 层处理的 Spring 上下文.扫描控制器类并创建 bean,因此在 MockMvc 上执行的请求可以访问端点。这里的重要部分是其他组件(层)不会自动扫描和注入。这就是错误状态的原因:

    创建名为“consumerController”的 bean 时出错:不满足的依赖性 (...)

    Spring 尝试创建控制器 bean,但找不到服务 bean。 @MockBean 通知 Spring 应该创建模拟并将其用作 bean。这就是使用此注释的测试有效的原因 - 可以正确创建 Spring 上下文并且可以注入 bean。其中一些(服务)作为模拟。

    有关详细信息,请参阅说明和示例:Testing the Web Layer in Spring docs

    此外,here 您可以找到一个使用@TestConfiguration 以编程方式创建的间谍 bean 的示例。这类似于使用 @SpyBean 注释,但可以在一些更复杂的情况下提供帮助,这里值得注意。为了简化:@TestConfigurationmock的工作方式类似于@MockBean,这使得Spring测试配置更加容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-18
      • 2023-03-30
      • 1970-01-01
      • 2023-03-20
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      相关资源
      最近更新 更多