Java 如何使用Junit和Mockito使用spring存储库测试void方法

Java 如何使用Junit和Mockito使用spring存储库测试void方法,java,junit,mocking,Java,Junit,Mocking,我有一个调用spring数据存储库的java spring服务,我想用mockito做一个Junit测试,这是我的类和我想测试的服务: @Service public class DataServiceImpl implements DataService{ @Autowired private CautionRepository cautionRepository; @Override public void addCautions(Li

我有一个调用spring数据存储库的java spring服务,我想用mockito做一个Junit测试,这是我的类和我想测试的服务:

@Service
public class DataServiceImpl implements DataService{

    @Autowired
    private CautionRepository cautionRepository;



        @Override
        public void addCautions(List<CautionsDTO> cautions, Contrat contrat) {

            if(cautions != null && !cautions.isEmpty()) {
                cautions.forEach(caution -> {

                        Caution caution = new Caution();

                        cautionContrat.setAmount(caution.getAmount());
                        cautionContrat.setDate(caution.getDate());

                        caution.setContrat(contrat);

                        cautionRepository.save(caution);
            });
            }
        }
    }

你知道我的测试有什么错误吗首先,你忘了在注意事项列表中添加注意事项。但除此之外,您正在混合单元测试和集成测试

您需要使用@RunWith(MockitoJUnitRunner.class)注释您的测试类

您需要使用@MockBean注释您的模拟对象,并将@Autowired添加到测试类DataServiceImpl对象中

现在,让我向你解释

单元测试

当您想要编写单元测试时,您应该不要使用应用程序上下文(自动连接)

顺便说一下,更好的方法是使用Lombok中的@RequiredArgsConstructor注释DataServiceImpl,并从存储库中删除@Autowired。这将允许您在单元测试的设置方法中实例化DataServiceImpl

您的DataServiceImpl类应为:

@Service
@RequiredArgsConstructor
public class DataServiceImpl implements DataService{

    private final CautionRepository cautionRepository;

    @Override
    public void addCautions(List<CautionsDTO> cautions, Contrat contrat) {
        // your code...
    }
}
集成测试

现在,如果您想创建集成测试,请使用@RunWith(SpringRunner.class)。通过这样做,您的应用程序上下文将被加载。在本例中,您可以通过使用@MockBean注释对象,在上下文中创建模拟bean。这将把模拟对象注入到您的上下文中,它将自动连接到您的真实类中

为此,您的新DataServiceImpl类可以保持与上面相同。但将集成测试更改为:

@RunWith(SpringRunner.class)
public class DataServiceImplTest{

    @Autowired
    private DataServiceImpl dataService;

    @MockBean // it will be injected automatically
    private CautionRepository cautionRepository;

    @Test
    public void addListCautionsTest() {
        // your test code...
    }
}

希望,您现在明白了其中的区别和您所犯的错误:)

首先,您忘了将警告对象添加到警告列表中。但除此之外,您正在混合单元测试和集成测试

您需要使用@RunWith(MockitoJUnitRunner.class)注释您的测试类

您需要使用@MockBean注释您的模拟对象,并将@Autowired添加到测试类DataServiceImpl对象中

现在,让我向你解释

单元测试

当您想要编写单元测试时,您应该不要使用应用程序上下文(自动连接)

顺便说一下,更好的方法是使用Lombok中的@RequiredArgsConstructor注释DataServiceImpl,并从存储库中删除@Autowired。这将允许您在单元测试的设置方法中实例化DataServiceImpl

您的DataServiceImpl类应为:

@Service
@RequiredArgsConstructor
public class DataServiceImpl implements DataService{

    private final CautionRepository cautionRepository;

    @Override
    public void addCautions(List<CautionsDTO> cautions, Contrat contrat) {
        // your code...
    }
}
集成测试

现在,如果您想创建集成测试,请使用@RunWith(SpringRunner.class)。通过这样做,您的应用程序上下文将被加载。在本例中,您可以通过使用@MockBean注释对象,在上下文中创建模拟bean。这将把模拟对象注入到您的上下文中,它将自动连接到您的真实类中

为此,您的新DataServiceImpl类可以保持与上面相同。但将集成测试更改为:

@RunWith(SpringRunner.class)
public class DataServiceImplTest{

    @Autowired
    private DataServiceImpl dataService;

    @MockBean // it will be injected automatically
    private CautionRepository cautionRepository;

    @Test
    public void addListCautionsTest() {
        // your test code...
    }
}

希望,您现在了解了差异和您所犯的错误:)

您从未向
警告添加值,因此循环不会执行,验证必须失败

向列表中添加一个值,测试应通过:

    List<CautionsDTO> cautions = new ArrayList<>(); 
    ContratExportation contrat = new ContratExportation();

    CautionDTO caution = new CautionDTO();
    cautions.add(caution);
    dataDelService.addCautions(cautions,contrat);
列出注意事项=新建ArrayList();
CONTRATEXPORATION contrat=新CONTRATEXPORATION();
告诫到告诫=新告诫到();
注意事项。添加(注意事项);
数据删除服务。添加注意事项(注意事项、合同);

您从不向
警告添加值,因此循环不会执行,验证必须失败

向列表中添加一个值,测试应通过:

    List<CautionsDTO> cautions = new ArrayList<>(); 
    ContratExportation contrat = new ContratExportation();

    CautionDTO caution = new CautionDTO();
    cautions.add(caution);
    dataDelService.addCautions(cautions,contrat);
列出注意事项=新建ArrayList();
CONTRATEXPORATION contrat=新CONTRATEXPORATION();
告诫到告诫=新告诫到();
注意事项。添加(注意事项);
数据删除服务。添加注意事项(注意事项、合同);

这应该是执行测试的正确代码

@RunWith(SpringRunner.class)
public class DataServiceImplTest{

@Autowired
private DataServiceImpl dataService;

@MockBean
private CautionRepository cautionRepository;

    @Test
    public void addListCautionsTest() {

        List<CautionsDTO> cautions = new ArrayList<>(); 
        ContratExportation contrat = new ContratExportation();

        Caution caution = new Caution();

         dataDelService.addCautions(cautions,contrat);

        Mockito.verify(cautionRepository, times(1)).save(caution);

    }
}
@RunWith(SpringRunner.class)
公共类DataServiceImplTest{
@自动连线
私有数据服务MPL数据服务;
@蚕豆
私有存储库;
@试验
公共无效addListCautionsTest(){
列出注意事项=新的ArrayList();
CONTRATEXPORATION contrat=新CONTRATEXPORATION();
注意=新的注意();
数据删除服务。添加注意事项(注意事项、合同);
Mockito.verify(警告存储库,次(1)).save(警告);
}
}

这应该是执行测试的正确代码

@RunWith(SpringRunner.class)
public class DataServiceImplTest{

@Autowired
private DataServiceImpl dataService;

@MockBean
private CautionRepository cautionRepository;

    @Test
    public void addListCautionsTest() {

        List<CautionsDTO> cautions = new ArrayList<>(); 
        ContratExportation contrat = new ContratExportation();

        Caution caution = new Caution();

         dataDelService.addCautions(cautions,contrat);

        Mockito.verify(cautionRepository, times(1)).save(caution);

    }
}
@RunWith(SpringRunner.class)
公共类DataServiceImplTest{
@自动连线
私有数据服务MPL数据服务;
@蚕豆
私有存储库;
@试验
公共无效addListCautionsTest(){
列出注意事项=新的ArrayList();
CONTRATEXPORATION contrat=新CONTRATEXPORATION();
注意=新的注意();
数据删除服务。添加注意事项(注意事项、合同);
Mockito.verify(警告存储库,次(1)).save(警告);
}
}

谢谢您的解释:)谢谢您的解释:)