如何在正常实例化的Service类中只注入一个模拟到其他实例?

问题描述

假设我已经实现了下一个服务类:

@Service
@RequiredArgsConstructor
@Transactional
public class ItemService {

    private final ItemRepository itemRepository;
    private final ItemCreatorFactory itemCreatorFactory;
    private final CommonClient commonClient;
    private final HelperService helperService;
    private final PrivilegeUtil privilegeUtil;

    public void addItem() {
        //How to only mock this in tests and other defaults to normal Autowired injection
        if(!privilegeUtil.isAdmin("bla bla")) {
             Throw new InvalidOperationException("Only super admin can insert data.");
        }
        helperService.doSomeRealLogic();
        commonClient.callAnotherExternalAPI();
        itemRepository.save(myObject);
    }
    // other methods
}

我需要测试在数据库中插入新项目,但是在此之前,我会做一些额外的逻辑,如果可以的话,我可以安全地插入数据库中。

现在我需要使用Mockito,所以我只模拟privilegeUtil类,但我需要ItemService类中的所有其他实例通常自动装配而不模拟它。

所以我要去下一个测试课:

@RunWith(SpringRunner.class)
public class ItemTests {

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @InjectMocks//Only mocks privilegeUtil but other instances is all null :(
    private ItemService itemService;//So how i get autowired item service instance but only mock privilegeUtil instance inside it and all other instances go for normal instantiation ???

    @Mock
    private PrivilegeUtil privilegeUtil;

    @Test
    public void testAddNewItem() {
        String email = "super@mail.com";

        Mockito.when(privilegeUtil.isSuperAdmin(email)).thenReturn(true);
        
        //Here i need to test adding item normally
        //But only skip checking isSuperAdmin part inside addItem method
        itemService.addItem(itemRequest,email);
    }

}

因此,我如何获取自动装配的项目服务实例,但其中仅包含模拟的utilityUtil实例以及所有其他实例进行常规实例化?

可以吗?否则,您可以提出什么建议?

解决方法

是的,这是可能的。正如您提到的那样,您测试了一些与数据库相关的逻辑,我想使用@TestConfiguration来让Spring与所有JPA /数据库相关的组件为您创建their documentation很有道理。

然后您就可以在测试中自动连接存储库了。

剩下的是使用例如手动创建所有其他 normal 豆。 @MockBean。您想模拟的那些类,用@RunWith(SpringRunner.class) @DataJpaTest public class ItemTests { @TestConfiguration static class TestConfig { @Bean public ItemCreatorFactory itemCreatorFactory() { return new ItemCreatorFactory(); } // .. manually create all other beans } @Autowired private ItemRepository itemRepository; @Autowired private ItemCreatorFactory itemCreatorFactory; @Autowired private CommonClient commonClient; @Autowired private HelperService helperService; @MockBean private PrivilegeUtil privilegeUtil; @Before public void setUp() throws Exception { this.itemService = new ItemService(itemRepository,itemCreatorFactory,commonClient,helperService,mockedPrivilegeUtil); } @Test public void testAddNewItem() { String email = "super@mail.com"; Mockito.when(privilegeUtil.isSuperAdmin(email)).thenReturn(true); itemService.addItem(itemRequest,email); } } 进行注释,以便Spring将模拟的版本放入切片的上下文中。

ItemService

...,然后您最终可以手动实例化{{1}}并将所有实例传递给构造函数。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...