[英]Testing a spring boot controller which has dependencies? (jUnit)
I have this test class : 我有这个测试课:
@RunWith(SpringRunner.class)
@WebMvcTest(ClassToBeTested.class)
public class ClassToBeTestedTests {
@Autowired
private MockMvc mockMvc;
@Test
public void simpleTestMethodToGetClassWorking(){
Assert.assertTrue(true);
}
}
but in the class I want to test, I have this line : 但是在我要测试的课程中,我有这行:
@Autowired
AnnoyingServiceWhichIsADependency annoyingDependency;
So when I try to run the test class - I get this error : 因此,当我尝试运行测试类时,出现此错误:
java.lang.IllegalStateException: Failed to load ApplicationContext
and the cause by line seems to throw this up : 和逐行原因似乎抛出了这个:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ClassToBeTested': Unsatisfied dependency expressed through field 'AnnoyingServiceWhichIsADependency'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '<package-path>.AnnoyingServiceWhichIsADependency' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
I will add that the actual class does work, and does what it is meant to do, but I am having trouble making it work in the unit test world. 我要补充的是,实际的类确实可以正常工作,并且可以完成它的本意,但是我在使它在单元测试领域中工作时遇到了麻烦。
All help appreciated. 所有帮助表示赞赏。
The reason a bean is not created for the dependency class is that you're using @WebMvcTest
and not @SpringBootTest
: only controllers and the MVC infrastructure classes are scanned. 未为依赖关系类创建bean的原因是,您使用的是
@WebMvcTest
而不是@SpringBootTest
:仅扫描控制器和MVC基础结构类。 From the docs : 从文档 :
Can be used when a test focuses only on Spring MVC components.
当测试仅针对Spring MVC组件时可以使用。
Since it's an MVC test, you can mock the service dependency. 由于它是MVC测试,因此可以模拟服务依赖关系。 Example: https://reflectoring.io/spring-boot-web-controller-test/
示例: https : //reflectoring.io/spring-boot-web-controller-test/
Your test application context is trying to load your ClassToBeTested but is unable to find one of its dependencies and complains about it via that error. 您的测试应用程序上下文正在尝试加载ClassToBeTested,但无法找到其依赖项之一,并通过该错误进行投诉。 Basically you need to have a @Bean of that type in your test context.
基本上,您需要在测试上下文中具有该类型的@Bean。 An option will be to create a TestConfig class which provides a Mock/Spy of that dependency via @Bean annotation.
一个选项是创建一个TestConfig类,该类通过@Bean批注提供该依赖项的Mock / Spy。 In your test you will have to load inside the context via the @ContextConfiguration annotation this test config you just created.
在测试中,您将必须通过@ContextConfiguration批注在刚才创建的测试配置中加载上下文。
https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-testing-annotation-contextconfiguration https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-testing-annotation-contextconfiguration
@WebMvcTest is only going to scan the web layer- the MVC infrastructure and @Controller classes. @WebMvcTest仅用于扫描Web层-MVC基础结构和@Controller类。 That's it.
而已。 So if your controller has some dependency to other beans from, eg form your service layer, they won't be found to be injected.
因此,如果您的控制器对其他Bean有某种依赖性,例如从您的服务层形成的其他Bean,则不会发现它们被注入。
If you want a more comprehensive integration test, use @SpringBootTest instead of @WebMvcTest 如果要进行更全面的集成测试,请使用@SpringBootTest而不是@WebMvcTest
If you want something closer to a unit test, mock your dependency. 如果您想要更接近单元测试的内容,请模拟您的依赖关系。
Also note that Field injection (@Autowired directly on the field) is not recommended exactly for these reasons. 还要注意,由于这些原因,不建议完全使用现场注入(@Autowired直接在现场)。 I recommend you change to constructor injeciton ( add a constructor for Classtobetested and place the @Autowired annotation on it. ) Then for a unit test you can pass in a mock.
我建议您更改为构造函数注入(为Classtobetested添加一个构造函数,并在其上放置@Autowired批注。)然后对于单元测试,您可以传递一个模拟。 Constructor injection leads to a more testable and configurable design.
构造函数注入导致更可测试和可配置的设计。
Just mock that dependency. 只是嘲笑这种依赖性。 Assuming that
AnnoyingServiceWhichIsADependency
is an interface: 假设
AnnoyingServiceWhichIsADependency
是一个接口:
@RunWith(SpringRunner.class)
@WebMvcTest(ClassToBeTested.class)
public class ClassToBeTestedTests {
@Autowired
private MockMvc mockMvc;
@MockBean
private AnnoyingServiceWhichIsADependency annoyingDependency;
@Test
public void simpleTestMethodToGetClassWorking(){
Assert.assertTrue(true);
}
}
Use Mockito when
and thenReturn
methods to instruct the mock. 使用Mockito
when
和thenReturn
方法来指导模拟。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.