当前位置: 首页 > 知识库问答 >
问题:

单元测试中未触发Spring特性

陈浩
2023-03-14

好的,我们说的是Spring(3.2.0)MVC

我们有一个被定义为“围绕”这样的注释触发的切入点:

@Around("@annotation(MyAnnotation)")
public void someFunction() {

}

然后在控制器中,我们有:

@Controller
@Component
@RequestMapping("/somepath")
public class MyController {

    @Autowired
    private MyService service;

    ...

    @MyAnnotation
    @RequestMapping(value = "/myendpoint", method = RequestMethod.POST, produces = "application/json")
    @ResponseBody
    public Object myEndpoint(@RequestBody MyRequestObject requestObject, HttpServletRequest request, HttpServletResponse response) {
        ...
        return service.doSomething(requestObject);
    }         
}

然后我们有一个单元测试,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"../path/to/applicationContext.xml"})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
public class MyControllerTest {

    private MockMvc mockMvc;

    @InjectMocks
    private MyController controller;

    @Mock
    private MyService myService;    

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
    }


    @Test
    public void myTest() {
        MyRequest request = new MyRequest();
        MyResponse response = new MyResponse();
        String expectedValue = "foobar";

        Mockito.when(myService.doSomething((MyRequest) Mockito.any())).thenReturn(response);

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post("/myendpoint");

        String request = IOUtils.toString(context.getResource("classpath:/request.json").getURI());

        builder.content(request);
        builder.contentType(MediaType.APPLICATION_JSON);

        mockMvc.perform(builder)
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.someKey").value(expectedValue));

        Mockito.verify(myService, Mockito.times(1)).doSomething((MyRequest) Mockito.any());
    }
}

测试运行正常,但围绕注释(MyAnnotation)定义的方面不会执行。当endpoint由实际请求触发时(例如,在servlet容器中运行时),这会很好地执行,但在测试中运行时不会触发。

这是MockMvc的一个特殊“功能”,它不会触发方面吗?

仅供参考我们的应用程序上下文。xml配置为:

<aop:aspectj-autoproxy/>

正如我提到的,这些方面在现实中确实有效,只是在测试中无效。

有人知道如何激发这些方面吗?

谢谢!

共有3个答案

卫嘉佑
2023-03-14

你需要在测试中启用aop:

@EnableAspectJAutoProxy
@RunWith(SpringJUnit4ClassRunner.class)
public class MyControllerTest {

}
齐元章
2023-03-14

我有一个类似的设置,使用MockMVC通过层执行集成测试。在我重命名注释的包之前,注释在没有任何额外代码的情况下运行良好。它停止工作了。注释将不执行。敲了一会儿头后,我意识到我已经解决了这个问题:组件扫描注释的包。

在应用程序的一个配置类文件中可能有类似的语句。您需要在测试类中重复这些类型的声明。

@SpringBootTest
@AutoConfigureMockMvc
@ComponentScan("annotation.package")
public class MyControllerTest {

}
梁丘宏硕
2023-03-14

好的...所以解决方案最终出现了...你猜对了...阅读留档:/

http://docs.spring.io/spring-framework/docs/3.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#spring-mvc-test-framework

此外,您可以通过Spring配置将模拟服务注入控制器中,以便集中精力测试web层。

所以最终的解决方案是这样的:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"testContext.xml","../path/to/applicationContext.xml"})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
public class MyControllerTest {

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private MyService myService;    

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @Test
    public void myTest() {
        MyRequest request = new MyRequest();
        MyResponse response = new MyResponse();
        String expectedValue = "foobar";

        Mockito.when(myService.doSomething((MyRequest) Mockito.any())).thenReturn(response);

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post("/myendpoint");

        String request = IOUtils.toString(context.getResource("classpath:/request.html" target="_blank">json").getURI());

        builder.content(request);
        builder.contentType(MediaType.APPLICATION_JSON);

        mockMvc.perform(builder)
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.someKey").value(expectedValue));

        Mockito.verify(myService, Mockito.times(1)).doSomething((MyRequest) Mockito.any());
    }
}

然后,您只需为这个testtestContext.xml定义一个上下文文件,该文件具有服务对象的模拟:

<bean id="myService" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.mypackage.MyService"/>
</bean>

重要的是,MyService实例是@Autowired到测试中的,因此可以对其进行编排。

这允许您模拟任何您喜欢的实例,无论它们是在服务类、方面等中,只要您适当地命名bean。因此在这种情况下,MyService将声明为:

@Component("myService")
public class MyService {
...
 类似资料:
  • 从装VS 2017开始,我就一直在纠结。现在看来,单元测试只能从命令行“dotnet test”运行。 我在MSDN(https://MSDN.microsoft.com/en-us/library/ms182532.aspx)上尝试了该示例,但同样失败。 测试和主项目的所有NuGet软件包都是当前的。并且测试项目和主项目都没有错误生成。从命令行成功运行测试。 有没有人在VS2017中进行单元测试

  • 我在自定义对象上有一个简单的“插入后”触发器来更新picklist值。基于某些IF条件,我正在更新picklist值,这在webservice或UI手动插入中运行良好,但当我为其编写单元测试用例时,picklist值总是返回null。选择列表值取决于插入记录后的触发器执行。我没有控制选取列表值。我正在创建测试数据,它将返回除picklist值之外的所有字段的值。是否需要显式设置值?

  • 我有一个Java项目,它使用了一些Azure函数,如HttpTrigger和QueueTrigger。我使用原型来生成这个项目,因此它可以使用HttpTrigger的一些样板代码和它的单元测试,但对QueueTrigger没有任何帮助。我正试图得到帮助,为这个QueueTrigger编写一个好的单元测试,它实际上是从队列中读取消息(弹出)。队列的代码如下所示: 有没有人能推荐一下这个队列触发azu

  • 我有一个春靴项目。我已经在.../src/test/java/...中编写了单元测试。目录。我的所有单元测试的形式都是*test.java。当我运行“MVN测试”时,我得到以下输出: 在这方面的任何帮助都是非常感谢的。 我没有展示我的全部POM。以下是Junit的内容:

  • 我对SpringBoot非常陌生,并试图学习如何在SpringBoot中进行测试。我读到了@SpringBootTest注释,它有助于集成测试应用程序。我想知道在SpringBoot中应该如何进行单元测试。单元测试是否需要指定@SpringBootTest注释,还是仅用于集成测试?是否有用于单元测试的特定注释? 任何指点都将不胜感激。提前谢谢! 编辑:SpringBootTest注释是否仅用于集成

  • 问题内容: 我想对一个模拟占位符的指令进行单元测试,其中仅在键入/按下事件时才清除输入值。 问题答案: 您需要以编程方式创建一个事件并触发它。为此,将jQuery用于单元测试非常有用。例如,您可以编写一个简单的实用程序,如下所示: 然后在您的单元测试中使用它,如下所示: 您可以在http://angular-ui.github.io/bootstrap/项目中查看此技术的实际应用:https :

  • 我使用的是一个用MapStruct生成的映射器: 缺省组件模型是spring(在pom.xml中设置)