@MockBeans 示例使用

@MockBeans example use

我有一个使用多项服务的控制器 class。我为该控制器编写了一个测试,例如:

@RunWith(SpringRunner.class)
@WebMvcTest(value = PurchaseController.class, secure = false)
public class PurchaseControllerTest {

    @MockBean
    private ShoppingService shoppingService;

    @MockBean
    private ShopRepository shopRepository;

    @MockBean
    private SomeOtherRepository someOtherRepository;

    @Autowired
    private MockMvc mockMvc;

// ... some tests goes here

事实是,这些模拟往往很多,因此代码行很多。我知道这可能是代码异味的迹象,但现在我的意思不是这个。

我注意到还有一个带有 @Target(ElementType.TYPE)@MockBeans 注释。所以我想我可以试试:

@RunWith(SpringRunner.class)
@WebMvcTest(value = PurchaseController.class, secure = false)
@MockBeans(value = {ShoppingService.class, ShopRepository.class})
public class PurchaseControllerTest {

但它不会编译。

我的问题是:我们如何使用 @MockBeans 注释?它适用于我的情况吗?

@MockBeans 它只是 @MockBean 的乘法的可重复注释。如果你需要重用这个模拟 bean,你可以在 class / config class 中添加。但是您需要使用 @Autowired 来获取您要模拟的服务。所以在你的情况下它应该是:

.....
@MockBeans({@MockBean(ShoppingService.class), MockBean(ShopRepository.class)})
public class PurchaseControllerTest {
  @Autowired
  ShoppingService shoppingService;
  @Autowired
  ShopRepository shopRepository;
.....
}

@MockBeans的主要思想就是在一处重复@MockBean。对我来说,它可能仅对您可以重复使用的某些配置/通用 class 有用。

@MockBean - 创建一个模拟,@Autowired - 是来自上下文的自动装配 bean,在你的情况下,它 mark/create bean 作为模拟然后模拟 bean 将被注入你的自动装配字段.

因此,如果您有很多带有 @MockBeans(或相乘 @MockBean)的自动装配字段,您可以在一个地方配置它是否为模拟(在 @MockBeans 中 class level)并且你不需要在测试 class 中将 @Autowired 更改为 @Mock(就像你的情况一样,如果你删除 @MockBeans 所有自动装配的 beans未模拟的将作为来自上下文的 beans 自动装配,如果您撤消删除,您将在模拟的 beans 中工作(您在此注释中配置)。

如果你想避免一个 class 内部的大量依赖,你可以将所有依赖提取到某个父 class 中,但是由于 java 不支持 class 它并不总是有帮助。

Javadoc 说它被用作

Container annotation that aggregates several {@link MockBean} annotations.

所以你可以这样写

@MockBeans({@MockBean(ShoppingService.class), @MockBean(ShopRepository.class)})
public class PurchaseControllerTest {

@Autowire ShoppingService 在这里工作

Can also be used in conjunction with Java 8's support for repeatable annotations

@MockBean(ShoppingService.class)
@MockBean(ShopRepository.class)
public class PurchaseControllerTest {

Java 8 启用可重复注释,并且出于兼容性原因,重复注释存储在由[自动生成的容器注释@MockBeans中=37=]编译器。为了让编译器执行此操作,您需要两件事:

  • 可重复@Repeatable(MockBeans.class)注释类型@MockBean
  • 包含注释类型@MockBeans

在您的案例中最短的变体是 @MockBean,它支持 mocks

所需 类 的多个值
@MockBean({ShoppingService.class, ShopRepository.class})