bounty将在19小时后到期。回答此问题可获得+100声望奖励。Swaraj Shekhar希望引起更多关注这个问题。
我得到空指针异常,而我试图模拟
@WebMvcTest(IMnJobManager.class)
public class CMnJobManagerTest {
@Autowired
private MockMvc mockmvc;
@Test
public void testExample()throws Exception{
IMnAllWorkFlows allWorkFlows = Mockito.mock(IMnAllWorkFlows.class);
Mockito.doAnswer(
invocation -> {
return Arrays.asList( "modn-ops");
}).when(allWorkFlows).getAllTenants();
mockmvc.perform(get("/v1/tenant"))
.andExpect(status().isOk())
.andExpect(content().string("modn-ops"))
.andDo(print());
}
}
我收到以下错误:
java.lang.NullPointerException
at com.test.manager.CMnJobManagerTest.testExample(CMnJobManagerTest.java:32)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
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.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
我的接口实现类如下所示:
@RestController
public class CMnJobManager implements IMnJobManager {
@Autowired
public CMnJobManager(IMnAllWorkFlows allWorkFlows, IMnWorkflowService workflowService,
IMnTemporalServiceClient temporalServiceClient, IMnWorkflowHistoryService workflowHistoryService,
IMnSearchAttributeService searchAttributeService, IMnS3Tenant s3Tenant) {
this.allWorkFlows = allWorkFlows;
this.workflowService = workflowService;
this.searchAttributeService = searchAttributeService;
this.workflowHistoryService = workflowHistoryService;
this.temporalServiceClient = temporalServiceClient;
this.s3Tenant = s3Tenant;
}
.
.
.
@Autowired
private HttpServletRequest request;
@Autowired
private CMnCustomMetricService customMetricService;
}
接口有很多方法,但我只想模拟一个。其余的调用,将调用IMnJobManager接口,因此我模仿了它。
错误说明问题出在mockMvc.perform(...),因此出现了NullPointerException。
当我从MockMvc中删除Autowired并添加mockMvc = MockMvcBuilders.standaloneSetup(allWorkFlows).build();
时,它给出404。
你知道这里有什么问题吗?
1条答案
按热度按时间dm7nw8vv1#
注解的作用以及如何正确使用Mockito来设置mock对象/test double似乎有很多困惑。
要开始,我建议阅读以下文章:
让我们先看看一些错误,最后再回来写一个工作测试。
@WebMvcTest
annotation的value
属性指定要在Spring上下文中加载的 Controllers。IMnJobManager
不是一个控制器,而是您的作业管理器界面。您希望传递CMnJobManager.class
。@WebMvcTest
only 加载应用程序的Web上下文(例如控制器)。从注解的JavaDoc:使用此注解将禁用完全自动配置,而仅应用与MVC测试相关的配置(即
@Controller
、@ControllerAdvice
、@JsonComponent
、Converter
/GenericConverter
、Filter
、WebMvcConfigurer
和HandlerMethodArgumentResolver
beans,但不包括@Component
、@Service
或@Repository
beans)。因此您的服务bean都不会被加载。
在相同的JavaDoc中进一步向下:
通常,
@WebMvcTest
与@MockBean
或@Import
结合使用,以创建@Controller
bean所需的任何协作者。那是什么意思?
@WebMvcTest(IMnJobManager.class)
不会创建任何端点,因为IMnJobManager
不是控制器,也没有定义任何请求Map。这一行显式地告诉Spring * 不加载 * 您的真实的控制器。尝试请求任何端点(使用mockmvc.perform(get(…))
)将导致404/NOT_FOUND。1.没有加载任何服务,我们必须(手动)为您的控制器创建协作者。我们将在下一节中处理这个问题。
这段代码创建了一个新的Mockito模拟对象,在其上存根一个方法,然后...什么都不做。示例是方法的本地示例,不存在于方法外部,也不能从外部访问。它 * 没有 * 在应用程序上下文中注册,并且不能由您的控制器使用。(现在是第二次阅读链接的Stackoverflow帖子的好时机)。
如何使示例作为控制器的协作者可用?我们按照注解的JavaDoc告诉我们的做:将其定义为
@MockBean
:然后在setup/
@BeforeEach
方法中存根该方法。在简单的测试中,例如问题中,也可以在测试本身中配置存根。解决上述所有问题应:
1.加载Web上下文
1.示例化控制器
1.创建协作者
1.为方法设置存根
这是一个简单但完整的演示项目(即一个Minimal, Reproducible Example,包含编译和执行代码所需的所有类),这表明上面概述的解决方案确实有效:
DemoService.java
:DemoController.java
:WebApplicationTest.java
: