【问题标题】:Creating beans when Autowiring with Spring使用 Spring 自动装配时创建 bean
【发布时间】:2017-07-05 23:59:17
【问题描述】:

我正在尝试为我的控制器编写测试。当 Web 服务运行时,一切正常。但是,当我运行测试时,我得到:

Error creating bean with name 'Controller': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.prov.Service' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

正如您在下面看到的,我相信所有内容都已正确自动装配,并且我的项目结构已正确设置,因此组件扫描仪可以正确找到注释,但我仍然收到此错误。

控制器:

@RestController
@RequestMapping("/api")
public class Controller {

    @Autowired
    private Service service;

    @JsonView(Views.All.class)
    @RequestMapping(value = "/prov/users", method = RequestMethod.POST)
    @ResponseBody
    public CommonWebResponse<String> handleRequest(@RequestBody UserData userData) {
        return service.prov(userData);  
    }
}

服务:

@Service
public class Service {

    @Autowired
    private Repo repo;

    @Autowired
    private OtherService otherService;

    public CommonWebResponse<String> prov(UserData userData) {
        // do stuff here
        return new SuccessWebResponse<>("Status");
    }
}

控制器测试:

@RunWith(SpringRunner.class)
@WebMvcTest(
        controllers = Controller.class,
        excludeFilters = {
                @ComponentScan.Filter(
                        type = FilterType.ASSIGNABLE_TYPE,
                        value = {CorsFilter.class, AuthenticationFilter.class}
                )
        }
)
@AutoConfigureMockMvc(secure = false)
public class ControllerTest {

    public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));

    @Autowired
    private MockMvc mvc;

    @Test
    public void connectToEndpoint_shouldReturnTrue() {
        UserData userData = new UserData("a", "bunch", "of", "fields");
        try {
            mvc.perform(post("/api/prov/users").contentType(APPLICATION_JSON_UTF8)
                    .content(asJsonString(userData))
                    .accept(MediaType.ALL))
                    .andExpect(status().isOk());
        } catch (Exception e) {
            Assert.fail();
        }
    }

}

【问题讨论】:

    标签: java spring spring-mvc dependency-injection autowired


    【解决方案1】:

    Controller 类自动装配您的 Service 类。因此,测试 Controller 类需要存在您的 Service 类,因为 Controller 依赖于创建 Service 类型的 bean。这意味着您要么必须 @Autowired 您的服务类进入您的测试,或者(最好)使用类似 Mockito 的东西来模拟它。

    (用代码示例编辑):

    @RunWith(SpringRunner.class)
    @WebMvcTest(Controller.class)
    public class ControllerTest {
        @MockBean
        private Service service
    
        @Autowired
        private MockMvc mvc;
    
        @Test
        public void foo() {
            String somePayload = "Hello, World";
            String myParams = "foo";
            when(service.method(myParams)).thenReturn(somePayload);
            mvc.perform(get("my/url/to/test").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", is(equalTo("Hello, World"))));
        }
    }
    

    请注意,此示例将 Hamcrest 用于 is()equalTo() 等内容

    【讨论】:

    • 谢谢,我之前曾尝试使用@MockBean 模拟服务,但我没有使用Mockito 模拟对服务的实际调用。我的最终方法与您提供的方法之间的唯一区别是我的参数和有效负载是自定义类对象,我不使用最后一行:.andExpect(jsonPath("$", is(equalTo("Hello, World"))));,因为我只需要显示端点是可访问的。
    • 我添加这些只是为了演示如何检查控制器返回的值。乐于助人!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 2012-06-15
    • 2012-08-11
    • 1970-01-01
    相关资源
    最近更新 更多