1

我有一个带有多个 spring bean 依赖项(自动装配服务)的 spring 控制器。每个服务也很少有 spring bean 依赖项(自动装配的 daos)。比如控制器登录方法:

@Controller
@RequestMapping("/")
public class ClientAccessController extends BaseController {

    @Autowired
    IFileService fileService;

    @Autowired
    MidTierService midTierService;

    /**
     * Used to handle client login requests
     * Works as a proxy to MID tier server
     *
     * @param request LoginRequest(userLogin, userPassword, compId, installGuid)
     * @return LoginResponse (token)
     * @throws Exception
     */
    @RequestMapping(method = RequestMethod.POST, value = "/login", headers = "Content-   type=application/json")
    public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest request) throws Exception {

        log.info("LOGIN REQUEST [ " + request.toString() + " ]");

        String token = midTierService.authenticateNativeClient(request.getLogin(), request.getPassword(), request.getGuId(),
                request.getCompid().toString());
        LoginResponse response = new LoginResponse(token);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        ResponseEntity<LoginResponse> responseEntity = new ResponseEntity<>(response, HttpStatus.OK);

        log.info("LOGIN RESPONSE [ " + response.toString());

        return responseEntity;
    }

我正在尝试仅为 controller 编写 JUnit 测试ClienAccessController。但是当我在测试类中自动装配时ClientAccessController,spring 会尝试为所有控制器依赖项和所有嵌套依赖项(daos 等)创建 bean,但我真的不需要 em,只有MidTierService. 那么我应该怎么做才能排除嵌套的bean初始化并只使用我在测试类中需要的东西呢?

4

2 回答 2

1

Spring 允许成员的方式不止一种@Autowired。对我来说(从可测试性的角度来看)首选的方法是@Autowired构造函数。所以我会为此创建一个构造函数ClientAccessController,如下所示:

@Autowired
public ClientAccessController(final IFileService fileService, final MidTierService midTierService) {
    this.fileService = fileService;
    this.midTierService = midTierService;
}

如果您的自动装配有点复杂(因为它使用@Qualifier@Value),则可以使用参数注释来完成更多操作。

@Autowired
public ClientAccessController(@Qualifier("myFileService") final IFileService fileService,
       @Qualifier("myMidTierService") final MidTierService midTierService) {
    this.fileService = fileService;
    this.midTierService = midTierService;
}

这样,您可以轻松地使用模拟对象或存根设置此类以进行测试。

@Test
public void testClientAccessController() {
    final IFileService mockFileService = Mockito.mock(IFileService.class);
    final MidTierService mockMidTierService = Mockito.mock(MidTierService.class);
    final ClientAccessController controller = new ClientAccessController(mockFileService, mockMidTierService);
    //test it
}
于 2012-10-30T13:09:21.650 回答
1

我没有创建一个将所有依赖项作为参数的构造函数,而是为每个依赖项创建了一个 set 方法。这样,我可以在测试中模拟这些依赖项,并使用 setter 注入它们。所以测试最终会是这样的:

@Test
public void testClientAccessController() {
    final IFileService mockFileService = Mockito.mock(IFileService.class);
    final MidTierService mockMidTierService = Mockito.mock(MidTierService.class);
    final ClientAccessController controller = new ClientAccessController();

    controller.setFileService(mockFileService);
    controller.setMidTierService(mockMidTierService);
    //test it
}

我还建议您创建这些设置器,protected并将测试用例与您正在测试的类放在同一个包中。

于 2013-04-08T17:01:28.740 回答