向“ @WebMvcTest”中添加一个额外的bean

时间:2019-05-07 11:34:52

标签: spring-boot spring-test

我有一个控制器和一个使用@WebMvcTest的测试,它运行良好。现在,我需要添加一些验证逻辑,为此,我需要@Autowired一个额外的bean(一个@Component,一个MapstructMapper)。

如预期的那样,由于@WebMvcTest,测试失败。 (未发现任何组件)

是否可以将一个bean添加到创建的上下文中?

由于我使用@MockBeans来模拟服务层:是否可以将所有模拟调用委派给真实对象?有了这个我可以模拟映射器并委托给真正的映射器?!

2 个答案:

答案 0 :(得分:2)

在上下文中获取其他bean的一种简单方法是通过在测试类中使用嵌套的配置类

 public static Pix readBitmap(Bitmap bmp) {
    if (bmp == null) {
        Log.e(LOG_TAG, "Bitmap must be non-null");
        return null;
    }
    if (bmp.getConfig() != Bitmap.Config.ARGB_8888) {
        Log.e(LOG_TAG, "Bitmap config must be ARGB_8888");
        return null;
    }

    long nativePix = nativeReadBitmap(bmp);

    if (nativePix == 0) {
        Log.e(LOG_TAG, "Failed to read pix from bitmap");
        return null;
    }

    return new Pix(nativePix);
}

示例:

场景-如果您有一些控制器,请说 ProductController ,并且对类有相应的切片测试,请说 ProductionControllerTest

@TestConfiguration
static class AdditionalConfig {
    @Bean
    public SomeBean getSomeBean() {
        return new SomeBean());
    }
}

相应的幻灯片测试类具有其他bean配置

@RestController
public class ProductController {

    @Autowired
    private IProductService productService;

    @Autowired
    private IProductValidator productValidator;


    @GetMapping("product")
    public Product getProduct(@RequestParam Long id) {

        Product product = productService.getProduct(id); // you are using mockBean of productService

        productValidator.validateProduct(product); // you need real bean of productValidator
        return product;
    }
}

有关您的方案的其他想法:如果您确实打算对控制器类进行单元测试,那么理想情况下,您应该模拟正在测试的类的所有其他依赖项。 理想情况下,单元测试的目的是仅测试被测对象/类的行为。所有相关类的行为或外部调用都应被模拟。
当您开始在一个测试下同时测试多个类时,您正朝着组件测试或集成测试迈进。

答案 1 :(得分:1)

一个非常简单的解决方案是用@Import注释您的测试类,例如,指定要在测试中使用的其他bean的类。

@WebMvcTest(MyController.class)
@Import(SomeOtherBean.class)
public class SourcingOrganisationControllerTests {

    // The controller bean is made available via @WebMvcTest  
    @Autowired
    private MyController myController;

    // Additional beans (only one in this case) are made available via @Import
    @Autowired
    private SomeOtherBean someOtherBean;
}