【问题标题】:@Mock jpaRepository calls real save method in other hand @MockBean calls mocked method@Mock jpaRepository 在另一方面调用真正的保存方法 @MockBean 调用模拟方法
【发布时间】:2019-01-18 12:09:51
【问题描述】:

我认为我理解@Mock 和@MockBean 之间的区别,即使我认为任何模拟的对象都不会调用真正的方法,尽管当我在测试下运行时,我可以看到篮子已插入到 hsqldb 日志中。所以现在我有点困惑,为什么使用@Mock时插入篮子,而使用@MockBean时不插入篮子。

INSERT INTO BASKET VALUES(5,'ABCDEFGHIJ','ACTIVE',1,'2019-01-18 12:00:36.066000','2019-01-18 12:00:36.066000')

另一方面,如果我这样做,那么 hsqldb 是干净的。在这两种情况下都测试成功。

@MockBean
private BasketRepository basketRepo;

测试类

@RunWith( SpringRunner.class )
@SpringBootTest( )
@ActiveProfiles( "test" )
public class BasketServiceTests
{

@SpyBean
private BasketService basketService;

@Mock
private BasketRepository basketRepo;

@Autowired
private UserAccountRepository userAccountRepo;

@Test
public void createBasketWithSameOrderRef() throws Exception
{
    UserAccount customer = userAccountRepo.findById( 1 )
            .orElseThrow( () -> new NotFoundException( "Customer not found" ) );

    Basket basket = new Basket();
    basket.setAudit( new Audit() );
    basket.setOrderRef( "ABCDEFGHIJ" );
    basket.setStatus( BasketStatusEnum.ACTIVE );
    basket.setUserAccount( customer );

    when( basketRepo.existsByOrderRef( anyString() ) ).thenReturn( false );
    when( basketRepo.save( isA( Basket.class ) ) ).thenReturn( basket );
    when( basketService.createOrderReference( ) ).thenReturn( "ABCDEFGHIJ" );

    Assert.notNull( basketService.getOrCreateByUserAccountBasket( customer ), "Basket id is null" );

}
}

服务

@Service
public class BasketService 
{
@Autowired
private BasketRepository basketRepo;

public Basket getOrCreateByUserAccountBasket( @NotNull final UserAccount userAccount )
{
    Optional<Basket> optBasket = basketRepo.findByUserAccountAndStatusActive( userAccount );

    if ( optBasket.isPresent() )
    {
        return optBasket.get();
    }

    String orderRef = null;

    do
    {
        orderRef = createOrderReference();
    }
    while( basketRepo.existsByOrderRef( orderRef ) );

    Basket basket = new Basket();
    basket.setAudit( new Audit() );
    basket.setOrderRef( orderRef );
    basket.setStatus( BasketStatusEnum.ACTIVE );
    basket.setUserAccount( userAccount );

    return basketRepo.save( basket );
}

public String createOrderReference()
{
    return RandomStringUtils.random( 10, true, false ).toUpperCase();
}
}

【问题讨论】:

    标签: java unit-testing spring-boot mockito junit4


    【解决方案1】:

    @MockBean 是一个 Spring 注释,应该在集成测试中使用,以便用模拟的 bean 替换真实的 bean:

    可用于向 Spring 添加模拟的注解 应用程序上下文。

    Mockitos @Mock 创建该存储库的模拟,但不会将其注入到 BasketService。

    如果您确实需要使用 Mockitos 模拟版本,则必须在测试中手动执行:

    @Mock
    private BasketRepository basketRepo;
    
    @Test
    public void createBasketWithSameOrderRef() throws Exception
    {
       basketService.setBasketRepository(basketRepo);
       ...
    

    如果您需要进一步阅读,我在Mockito Stubbing 上写了一篇文章。

    【讨论】:

    • 啊,我明白了!顺便说一句,我注释掉了前 2 个 when() - 与 basketRepo 相关联 - 我得到相同的结果,篮子被插入。因此,平均测试是使用 @Autowired basketRepo 而不是 mocked 一个。谢谢
    猜你喜欢
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    相关资源
    最近更新 更多