首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >@ SpringBoot中的MockBean注释不起作用

@ SpringBoot中的MockBean注释不起作用
EN

Stack Overflow用户
提问于 2021-01-12 23:12:27
回答 1查看 4.7K关注 0票数 1

我试图使用@MockBean注释来模拟服务,但我得到了以下错误:

org.springframework.beans.factory.BeanCreationException:无法注入字段: FooService FooTest.fooService;嵌套异常是java.lang.IllegalStateException: FooService fooService不能具有现有值

下面是我尝试使用的代码示例:

代码语言:javascript
运行
复制
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import org.springframework.test.context.junit4.SpringRunner;
        
    import FooService;
        
    @RunWith (SpringRunner.class)
    @SpringBootTest
    class FooTest {
        
    @Autowired
    FooService fooService;
    
    @MockBean
    BarService barService;
        
    @Test
    public void testMethod() throws Exception {
        
Mockito.doThrow(new ExceptionClass()).when(barService).externalWebSerivceCall();

//Verify @Retryable is calling 3 times
    
       }
    }
    
    class FooService {
        
    @Autowired
    BarService barService;
        
    @Retryable (value = ExceptionClass.class, maxAttempts = 3, backoff = @Backoff (delay = 3 * 60 * 1000))
    public void methodThatFails() {
        
       barService.externalWebSerivceCall();
        
    }


}

知道我能怎么解决吗?

下面是整个堆栈跟踪:

代码语言:javascript
运行
复制
org.springframework.beans.factory.BeanCreationException: Could not inject field: FooService FooTest.fooService; nested exception is java.lang.IllegalStateException: The field FooService FooTest.fooService cannot have an existing value

    at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.inject(MockitoPostProcessor.java:364)
    at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.inject(MockitoPostProcessor.java:352)
    at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.lambda$injectFields$0(MockitoTestExecutionListener.java:79)
    at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.postProcessFields(MockitoTestExecutionListener.java:100)
    at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.injectFields(MockitoTestExecutionListener.java:79)
    at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.prepareTestInstance(MockitoTestExecutionListener.java:54)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: java.lang.IllegalStateException: The field FooService FooTest.fooService cannot have an existing value
    at org.springframework.util.Assert.state(Assert.java:97)
    at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.inject(MockitoPostProcessor.java:358)
    ... 27 more
EN

回答 1

Stack Overflow用户

发布于 2021-01-13 00:51:41

我注意到您的服务类上没有@Service注释。@MockBean可能无法工作的原因之一是如果您不将类标记为@Service@Component

如果不是这样的话,我不清楚为什么@MockBean注释不适合您,但是根据您想要测试的内容,您可能希望只在@TestConfiguration方法中使用@RunWith(SpringRunner.class)和服务的@Autowired,而不是在类中使用@SpringBootTest。这肯定有效,并将允许您测试服务层。

下面是我根据文章测试的一个示例,该文章说:

要检查Service类,我们需要创建一个Service类的实例,并将其作为@Bean使用,这样我们就可以在我们的测试类中@Autowire了。我们可以使用@TestConfiguration注释来实现这个配置。 在组件扫描期间,我们可能会发现,只为特定测试创建的组件或配置在任何地方都会意外地被拾取。为了防止这种情况,Spring提供了@TestConfiguration注释,我们可以在src/test/java中的类上添加这个注释,以指示不应该通过扫描来获取它们。

代码语言:javascript
运行
复制
@RunWith(SpringRunner.class)
@DataJpaTest//good for working with JPA Components
// @SpringBootTest
class Tests {

    @TestConfiguration //tell spring that this configuration is only for testing environment
    static class UserDetailsServiceImplTextContext {
        @Bean //needed for creating instance for test autowiring
        public UserDetailsServiceImpl userDetailsServiceImpl() {
            return new UserDetailsServiceImpl();
        }
    }

    @Autowired
    private UserDetailsServiceImpl userServices;

    @Autowired
    TestEntityManager entityManager;

    @Test
    @DisplayName("Context Loads")
    void contextLoads() {
    }

    @Test
    @DisplayName("Create User")
    void createUser() {
        //given
        String a = "testUser";
        String email = "testUser@test.com";
        String username = a;
        String firstname = a;
        String lastname = a;
        String password = a;
        String userType = "USER";
        User u = new User(email, username, firstname, lastname, password, userType);
        //when
        entityManager.persist(u);
        entityManager.flush();
        //then
        User u2 = userServices.getUserRepo().findByUsername(username);
        //expect
        assertEquals(u, u2);
    }
}

另外,这篇文章中关于这个主题的另一节可能会有所帮助。这是一个使用@SpringBootTest的替代示例,显示了所涉及的附加配置。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65693420

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档