![](/img/trans.png)
[英]SpringBoot @WebMvcTest and @MockBean not working as expected
[英]@MockBean annotation in SpringBoot is not working
我正在嘗試使用 @MockBean 注釋模擬服務,但出現以下錯誤:
org.springframework.beans.factory.BeanCreationException:無法注入字段:FooService FooTest.fooService; 嵌套異常是 java.lang.IllegalStateException: FooService fooService 不能有現有值
這是我嘗試使用的代碼示例:
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();
}
}
知道如何解決嗎?
這是整個堆棧跟蹤:
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
我注意到您的服務 class 上沒有@Service
注釋。 @MockBean
可能不起作用的一個原因是,如果您不使用 label 將 class 作為@Service
或@Component
。
如果不是這樣,我不確定為什么@MockBean
注釋對您不起作用,但根據您要測試的內容,您可能只想使用@RunWith(SpringRunner.class)
和@TestConfiguration
方法和@Autowired
為您的服務而不是在您的 class 上使用@SpringBootTest
。 這絕對有效,並且允許您測試服務層。
這是我根據這篇文章測試過的一個例子,它說:
要檢查服務 class,我們需要創建服務 class 的實例並將其作為@Bean 提供,以便我們可以在測試 class 中對其進行@Autowire。 我們可以使用@TestConfiguration 注解來實現這個配置。
在組件掃描期間,我們可能會發現僅為特定測試創建的組件或配置會意外地隨處被拾取。 為了幫助防止這種情況,Spring Boot 提供了 @TestConfiguration 注釋,我們可以在 src/test/java 中的類上添加該注釋,以指示它們不應被掃描拾取。
@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的替代示例,顯示了所涉及的附加配置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.