在自动接线服务类中测试REST API时,如何使用测试application.yml覆盖main application.yml?

时间:2019-08-09 12:51:38

标签: rest spring-boot

我正在为我的应用程序的REST API使用TestNG编写自动化测试。该应用程序具有一个RestController,其中包含一个@Autowired服务类。当使用HTTP GET请求调用REST端点时,该服务将查找XML文件的存储目录,将其内容转换为对象并将其存储在数据库中。对于我的问题,重要的是,存储目录的路径存储在/src/main/resources/application.yml(source.storage)中,并通过@Value批注导入。

现在,我在src / test / resources / application.yml中也具有source.storage属性,它指向src / test中的另一个目录,我在其中存储测试XML文件,并使用再次@Value注释。我的测试使用HTTP GET调用REST端点。但是,该服务似乎仍在主application.yml中绘制source.storage属性,而我希望该值被测试application.yml文件中的值覆盖。换句话说,该服务尝试从应用程序存储目录而不是从我的测试存储导入XML文件。

@ActiveProfiles和@TestPropertySource对我似乎不起作用。扫描主应用程序.yml的存储属性是不可行的,因为最后,该application.yml是从Spring Cloud Config中提取的,我不知道主应用程序.yml的位置。

有没有一种方法可以使@Autowired服务从测试application.yml中而不是从主要应用程序中提取source.storage属性?

任何建议将不胜感激。

谢谢,彼得

2 个答案:

答案 0 :(得分:1)

好吧,这实际上取决于您要构建的内容,如果它是控制器的某种单元测试或更可能是集成测试。 tutorial对此方法进行了解释。

如果您尝试编写集成测试,这似乎更适合您的问题,那么@ActiveProfiles@TestPropertySource应该适合您。我建议使用配置文件,在具有许多属性的不断增长的应用程序中,只需替换一些用于测试的属性会更加方便。以下是为控制器端点编写集成测试时为我工作的设置:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class AreaControllerTest {

    @Autowired
    TestRestTemplate rest;

    @MockBean
    private JobExecutor jobExecutor;


    @Test
    public void test01_List() {
        //
    }

    @Test
    public void test02_Get() {
        //
    }

    // ...
}

有几件重要的事情。

  • 测试属性位于src/test/resources/application-test.properties中,并按照application.properties注释的建议覆盖标准@ActiveProfiles("test")中的属性。
  • 基本(Essential)也是JUnit专用的@RunWith(SpringRunner.class),有关TestNG的替代方法,请参考this SO question
  • 最后,@SpringBootTest批注将启动整个应用程序上下文。
  • @FixMethodOrder@DirtiesContext是测试用例的进一步设置,并非必需。
  • 还请注意@MockBean注释,在这种情况下,我们不想使用JobExecutor的实际实现,因此我们将其替换为模拟。

如果要编写单元测试,而只想单独检查控制器和服务的逻辑,则必须有两个测试类,每个测试类都测试各自的类。测试服务应该是标准的单元测试,测试控制器比较棘手,可能更倾向于部分集成测试。如果您是这种情况,我建议您使用上述教程中介绍的MockMvc方法。那里的小片段:

@RunWith(SpringRunner.class)
@WebMvcTest(GreetingController.class)
public class WebMockTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private GreetingService service;

    @Test
    public void greetingShouldReturnMessageFromService() throws Exception {
        when(service.greet()).thenReturn("Hello Mock");
        this.mockMvc.perform(get("/greeting")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello Mock")));
    }
}

请注意@MockBean注释,该注释模拟服务,您可以在其中指定自己的模拟行为。这一点很关键,因为这种测试不会加载整个应用程序上下文,而只会加载MVC上下文,因此服务不可用。同样,在集成测试中,@RunWith(SpringRunner.class)注释是必不可少的。最后,@WebMvcTest(GreetingController.class)仅启动GreetingController类的MVC上下文,而不是整个应用程序。

答案 1 :(得分:0)

您可以尝试将属性直接提供给Spring Boot测试。

UITextView

关于应用程序选择了错误的属性源,您还应该检查应用程序是否正确构建。