如何使用注释对Spring Controller进行单元测试?

时间:2017-10-14 14:57:54

标签: java spring spring-mvc spring-boot junit

我是Spring控制器单元测试概念的新手。我跟随我在网上找到的一些例子,试图实施他们的测试策略。这是我的基本控制器:

@Controller
public class GreetingController {

    @RequestMapping("/greeting")
    public String greeting(@RequestParam(value = "name2", required = false, defaultValue = "World2") String name2,
                           Model model) {

        model.addAttribute("name", name2);
        return "greeting";
    }

}

这是我的单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class ControllerGreetingTest {

    private MockMvc mockMvc;

    @Autowired
    GreetingController greetingController;
    @Test
    public void shouldReturnSomething() throws Exception {
        mockMvc.perform(get("/greeting"))
                .andExpect(status().isOk())
                .andExpect(view().name("greeting"));
    }

}

看起来非常直接,但我收到以下错误:

  

java.lang.IllegalStateException:既不是GenericXmlWebContextLoader   也没有AnnotationConfigWebContextLoader能够检测默认值,和   没有为上下文声明ApplicationContextInitializers   配置[ContextConfigurationAttributes @ 1698539 declaringClass =   ' com.practice.demo.ControllerGreetingTest',locations =' {}',班级   =' {}',inheritLocations = true,initializers =' {}&#39 ;, inheritInitializers = true,name = [null],contextLoaderClass =   ' org.springframework.test.context.ContextLoader']

我假设我必须在@ContextConfiguration注释中添加一个参数,但不知道该包含哪些内容。

EDIT =这是我到目前为止所做的:

public class ControllerGreetingTest {

    private MockMvc mockMvc;

   @Before
    public void setup(){
        this.mockMvc = standaloneSetup(new GreetingController()).build();
    }

    @Test
    public void shouldReturnDefaultString() throws Exception {
        mockMvc.perform(get("/greeting"))
                .andExpect(status().isOk())
                .andExpect(view().name("greetings"))
                .andExpect(model().attribute("name","World2"));
    }

}

它完成了这项工作,但它并没有像我之前尝试过的那样使用任何Spring注释......这种方法并不好,所以试图找出为什么每当我在我的注释中包含注释时我都会遇到错误测试文件。

我的POM:

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>1.5.7.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-all</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <artifactId>hamcrest-core</artifactId>
                <groupId>org.hamcrest</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>1.9.5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>3.2.3.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>3.4.2</version>
        </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>1.5.7.RELEASE</version>
        <scope>test</scope>
    </dependency>

</dependencies>

3 个答案:

答案 0 :(得分:3)

您应该使用spring-boot-starter-test依赖项。它几乎可以用于测试。

为了测试spring应用程序的控制器部分,您应该为测试类使用@WebMvcTest注释。使用此注释弹簧将仅为控制器部件加载上下文。另外,如果使用此注释,则无需设置方法。你可以简单地自动装配mockMvc。你的测试类应该是这样的:

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

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private SomeServiceClass someServiceClass;

    @Test
    public void shouldReturnDefaultString() throws Exception {
        mockMvc.perform(get("/greeting"))
            .andExpect(status().isOk())
            .andExpect(view().name("greetings"))
            .andExpect(model().attribute("name","World2"));
    }

}

注意:您的控制器没有任何自动装配的字段。如果控制器有一些自动对象,如服务或存储库对象。您可以使用注释@MockBean来模拟它们,如上所示。

有关提供的其他测试切片注释,请参阅this link

答案 1 :(得分:2)

对于org.springframework.boot:spring-boot-starter-test的项目,可以使用

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class ControllerGreetingTest {
    ...
}

其中App.class是您使用@SpringBootApplication注释的主要应用程序类。但你最好阅读documentation。如果您不想包含(classes = App.class)部分,您也可以更改folder structure

对于简单的控制器,可以执行简单的独立测试

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = ControllerGreeting.class)
public class ControllerGreetingTest {
    @Autowired
    private MockMvc mockMvc;

    ...

}

答案 2 :(得分:2)

只需添加@ContextConfiguration注释并引用一个或多个XML配置文件位置或一个或多个配置类。否则Spring无法对您的控制器进行自动装配,应对其进行测试。

示例:您想测试一个控制器,它通过@Autowired使用MyService:

MyControllerTest :注入控制器,应使用 MyTestConfig 配置类进行测试。

function curl_get_contents($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    $data = curl_exec($ch);
    curl_close($ch);
    return $data;
}

MyTestConfig :返回测试所需的所有bean。使用Mockito来模拟控制器的依赖性,因为我们只想测试控制器而不是服务层。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyTestConfig.class})
@WebAppConfiguration
public class MyControllerTest {

  private MockMvc mockMvc;

  @Autowired
  private MyController controller;

  @Before
  public void setUp() {
    mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
  }

  // Tests
}
相关问题