@Mock jpaRepository 调用真正的保存方法,另一方面@MockBean 调用模拟方法
@Mock jpaRepository calls real save method in other hand @MockBean calls mocked method
我以为我理解 @Mock
和 @MockBean
之间的区别,甚至我认为任何被模拟的对象都不会调用真正的方法,尽管当我 运行 在下面的测试中我可以看到篮子已经被插入在 hsqldb 日志上。所以现在有点疑惑为什么用@Mock
的时候插入basket而用@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;
测试class
@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();
}
}
@MockBean
是一个 Spring 注释,应该在集成测试中使用,以便用模拟 bean 替换真实 bean:
Annotation that can be used to add mocks to a Spring
ApplicationContext.
Mockitos @Mock
创建该存储库的模拟,但不会将其注入 BasketService
。
如果您确实需要使用 Mockitos 模拟版本,则必须在测试中手动执行:
@Mock
private BasketRepository basketRepo;
@Test
public void createBasketWithSameOrderRef() throws Exception
{
basketService.setBasketRepository(basketRepo);
...
如果您需要进一步阅读,我在 Mockito Stubbing 上写了一篇文章。
我以为我理解 @Mock
和 @MockBean
之间的区别,甚至我认为任何被模拟的对象都不会调用真正的方法,尽管当我 运行 在下面的测试中我可以看到篮子已经被插入在 hsqldb 日志上。所以现在有点疑惑为什么用@Mock
的时候插入basket而用@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;
测试class
@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();
}
}
@MockBean
是一个 Spring 注释,应该在集成测试中使用,以便用模拟 bean 替换真实 bean:
Annotation that can be used to add mocks to a Spring ApplicationContext.
Mockitos @Mock
创建该存储库的模拟,但不会将其注入 BasketService
。
如果您确实需要使用 Mockitos 模拟版本,则必须在测试中手动执行:
@Mock
private BasketRepository basketRepo;
@Test
public void createBasketWithSameOrderRef() throws Exception
{
basketService.setBasketRepository(basketRepo);
...
如果您需要进一步阅读,我在 Mockito Stubbing 上写了一篇文章。