Java 如何在TestNG中结合Mockito和Spring

Java 如何在TestNG中结合Mockito和Spring,java,spring,unit-testing,mockito,testng,Java,Spring,Unit Testing,Mockito,Testng,我们正在构建一个使用Spring引导的应用程序。我们使用TestNG和Mockito编写单元测试。然而,我发现在进行(…)配置时编写代码非常烦人,我希望使用真正的组件。我开始使用@Spy组件,而不是mock,在我需要将一个Spy放到一个Spy中之前,这种方法非常有效。如果可能的话,我希望避免加载Spring上下文,因为上下文的创建速度非常慢,对于我来说,加载最多5个类的上下文似乎有些过分 有没有办法,我怎么能用真实的代码代替模拟,而不加载整个Spring上下文?还是我的方法根本就错了,我应该模仿

我们正在构建一个使用Spring引导的应用程序。我们使用TestNG和Mockito编写单元测试。然而,我发现在进行(…)配置时编写代码非常烦人,我希望使用真正的组件。我开始使用@Spy组件,而不是mock,在我需要将一个Spy放到一个Spy中之前,这种方法非常有效。如果可能的话,我希望避免加载Spring上下文,因为上下文的创建速度非常慢,对于我来说,加载最多5个类的上下文似乎有些过分


有没有办法,我怎么能用真实的代码代替模拟,而不加载整个Spring上下文?还是我的方法根本就错了,我应该模仿所有其他类,然后是测试类?

我认为您使用
@ContextConfiguration
@Configuration

要测试的类

@Service
public class RecordServiceImpl implements RecordService
{
    @Autowired
    private RecordRepository recordRepository;

    public Record find(String id)
    {
        return recordRepository.findOne(id);
    }

    public List<Record> findAll()
    {
        return recordRepository.findAll();
    }

    @Transactional
    public Record save(Record record)
    {
        record.setRecordStatus("F");
        return recordRepository.save(record);
    }
}
@Service
public class RecordServiceImpl implements RecordService
{

    private final RecordRepository recordRepository;

    @Autowired
    public RecordServiceImpl(RecordRepository recordRepository)
    {
        this.recordRepository = recordRepository;
    }

    public Record find(String id)
    {
        return recordRepository.findOne(id);
    }

    public List<Record> findAll()
    {
        return recordRepository.findAll();
    }

    @Transactional
    public Record save(Record record)
    {
        record.setRecordStatus("F");
        return recordRepository.save(record);
    }
}

整个测试类花了714ms来运行
findAll
测试,花了1ms。

我认为您使用
@ContextConfiguration
@Configuration

要测试的类

@Service
public class RecordServiceImpl implements RecordService
{
    @Autowired
    private RecordRepository recordRepository;

    public Record find(String id)
    {
        return recordRepository.findOne(id);
    }

    public List<Record> findAll()
    {
        return recordRepository.findAll();
    }

    @Transactional
    public Record save(Record record)
    {
        record.setRecordStatus("F");
        return recordRepository.save(record);
    }
}
@Service
public class RecordServiceImpl implements RecordService
{

    private final RecordRepository recordRepository;

    @Autowired
    public RecordServiceImpl(RecordRepository recordRepository)
    {
        this.recordRepository = recordRepository;
    }

    public Record find(String id)
    {
        return recordRepository.findOne(id);
    }

    public List<Record> findAll()
    {
        return recordRepository.findAll();
    }

    @Transactional
    public Record save(Record record)
    {
        record.setRecordStatus("F");
        return recordRepository.save(record);
    }
}

整个测试类花了714ms运行
findAll
测试,花了1ms。

另一种方法是通过构造函数注入而不是字段注入来完成此操作,并且可能需要对代码进行一些修改。基本上不需要spring上下文进行测试。所以从另一个答案来看也是一样的

要测试的类

@Service
public class RecordServiceImpl implements RecordService
{
    @Autowired
    private RecordRepository recordRepository;

    public Record find(String id)
    {
        return recordRepository.findOne(id);
    }

    public List<Record> findAll()
    {
        return recordRepository.findAll();
    }

    @Transactional
    public Record save(Record record)
    {
        record.setRecordStatus("F");
        return recordRepository.save(record);
    }
}
@Service
public class RecordServiceImpl implements RecordService
{

    private final RecordRepository recordRepository;

    @Autowired
    public RecordServiceImpl(RecordRepository recordRepository)
    {
        this.recordRepository = recordRepository;
    }

    public Record find(String id)
    {
        return recordRepository.findOne(id);
    }

    public List<Record> findAll()
    {
        return recordRepository.findAll();
    }

    @Transactional
    public Record save(Record record)
    {
        record.setRecordStatus("F");
        return recordRepository.save(record);
    }
}
@服务
公共类RecordServiceImpl实现RecordService
{
私人最终记录库;
@自动连线
公共RecordServiceImpl(记录存储库记录存储库)
{
this.recordRepository=recordRepository;
}
公共记录查找(字符串id)
{
返回recordRepository.findOne(id);
}
公共列表findAll()
{
返回recordRepository.findAll();
}
@交易的
公共记录保存(记录)
{
记录。设置记录状态(“F”);
返回recordRepository.save(记录);
}
}
测试用例

//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = {RecordServiceTestConfig.class})
public class RecordServiceTest
{
//    @Autowired
    private RecordRepository recordRepository = Mockito.mock(RecordRepository.class);
//    @Autowired
    private RecordService    recordService;

    @Before
    public void setup()
    {
        Mockito.reset(recordRepository);
        recordService = new RecordServiceImpl(recordRepository);
    }

    @Test
    public void testFind()
    {
        Mockito.when(recordRepository.findOne(Mockito.anyString())).thenReturn(null);

        Record record = recordService.find("1");
        Assert.assertNull(record);
        Mockito.verify(recordRepository, Mockito.times(1)).findOne(Mockito.eq("1"));
    }

    @Test
    public void testSave()
    {
        Mockito.when(recordRepository.save(Mockito.any(Record.class)))
                .thenAnswer(new Answer<Record>()
                {
                    @Override
                    public Record answer(InvocationOnMock invocation) throws Throwable
                    {
                        Record record = (Record) invocation.getArguments()[0];
                        Assert.assertEquals("F", record.getRecordStatus());
                        return record;
                    }
                });

        Record record = new Record();
        record = recordService.save(record);
        Assert.assertNotNull(record);
        Mockito.verify(recordRepository, Mockito.times(1)).save(Mockito.eq(record));
    }

    @Test
    public void findAll()
    {

        Mockito.when(recordRepository.findAll()).thenReturn(new ArrayList<Record>());

        List<Record> records = recordService.findAll();
        Assert.assertNotNull(records);
        Assert.assertEquals(0, records.size());
        Mockito.verify(recordRepository, Mockito.times(1)).findAll();

    }
}
/@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(类={RecordServiceTestConfig.class})
公共类RecordServiceTest
{
//@自动连线
私有RecordRepository RecordRepository=Mockito.mock(RecordRepository.class);
//@自动连线
私人录音服务;
@以前
公共作废设置()
{
重置(记录存储库);
recordService=新的RecordServiceImpl(recordRepository);
}
@试验
公共void testFind()
{
Mockito.when(recordRepository.findOne(Mockito.anyString())。然后返回(null);
Record=recordService.find(“1”);
Assert.assertNull(记录);
验证(recordRepository,Mockito.times(1)).findOne(Mockito.eq(“1”));
}
@试验
公共void testSave()
{
Mockito.when(recordRepository.save(Mockito.any(Record.class)))
.thenAnswer(新答案)
{
@凌驾
公共记录应答(invocationMock调用)抛出可丢弃的
{
Record Record=(Record)invocation.getArguments()[0];
Assert.assertEquals(“F”,record.getRecordStatus());
返回记录;
}
});
记录=新记录();
record=recordService.save(记录);
Assert.assertNotNull(记录);
验证(recordRepository,Mockito.times(1)).save(Mockito.eq(record));
}
@试验
公共无效findAll()
{
Mockito.when(recordRepository.findAll()).thenReturn(newarraylist());
List records=recordService.findAll();
Assert.assertNotNull(记录);
Assert.assertEquals(0,records.size());
verify(recordRepository,Mockito.times(1)).findAll();
}
}

另一种方法是通过构造函数注入而不是字段注入来完成,这可能需要对代码进行一些修改。基本上不需要spring上下文进行测试。所以从另一个答案来看也是一样的

要测试的类

@Service
public class RecordServiceImpl implements RecordService
{
    @Autowired
    private RecordRepository recordRepository;

    public Record find(String id)
    {
        return recordRepository.findOne(id);
    }

    public List<Record> findAll()
    {
        return recordRepository.findAll();
    }

    @Transactional
    public Record save(Record record)
    {
        record.setRecordStatus("F");
        return recordRepository.save(record);
    }
}
@Service
public class RecordServiceImpl implements RecordService
{

    private final RecordRepository recordRepository;

    @Autowired
    public RecordServiceImpl(RecordRepository recordRepository)
    {
        this.recordRepository = recordRepository;
    }

    public Record find(String id)
    {
        return recordRepository.findOne(id);
    }

    public List<Record> findAll()
    {
        return recordRepository.findAll();
    }

    @Transactional
    public Record save(Record record)
    {
        record.setRecordStatus("F");
        return recordRepository.save(record);
    }
}
@服务
公共类RecordServiceImpl实现RecordService
{
私人最终记录库;
@自动连线
公共RecordServiceImpl(记录存储库记录存储库)
{
this.recordRepository=recordRepository;
}
公共记录查找(字符串id)
{
返回recordRepository.findOne(id);
}
公共列表findAll()
{
返回recordRepository.findAll();
}
@交易的
公共记录保存(记录)
{
记录。设置记录状态(“F”);
返回recordRepository.save(记录);
}
}
测试用例

//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = {RecordServiceTestConfig.class})
public class RecordServiceTest
{
//    @Autowired
    private RecordRepository recordRepository = Mockito.mock(RecordRepository.class);
//    @Autowired
    private RecordService    recordService;

    @Before
    public void setup()
    {
        Mockito.reset(recordRepository);
        recordService = new RecordServiceImpl(recordRepository);
    }

    @Test
    public void testFind()
    {
        Mockito.when(recordRepository.findOne(Mockito.anyString())).thenReturn(null);

        Record record = recordService.find("1");
        Assert.assertNull(record);
        Mockito.verify(recordRepository, Mockito.times(1)).findOne(Mockito.eq("1"));
    }

    @Test
    public void testSave()
    {
        Mockito.when(recordRepository.save(Mockito.any(Record.class)))
                .thenAnswer(new Answer<Record>()
                {
                    @Override
                    public Record answer(InvocationOnMock invocation) throws Throwable
                    {
                        Record record = (Record) invocation.getArguments()[0];
                        Assert.assertEquals("F", record.getRecordStatus());
                        return record;
                    }
                });

        Record record = new Record();
        record = recordService.save(record);
        Assert.assertNotNull(record);
        Mockito.verify(recordRepository, Mockito.times(1)).save(Mockito.eq(record));
    }

    @Test
    public void findAll()
    {

        Mockito.when(recordRepository.findAll()).thenReturn(new ArrayList<Record>());

        List<Record> records = recordService.findAll();
        Assert.assertNotNull(records);
        Assert.assertEquals(0, records.size());
        Mockito.verify(recordRepository, Mockito.times(1)).findAll();

    }
}
/@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(类={RecordServiceTestConfig.class})
公共类RecordServiceTest
{
//@自动连线
私有RecordRepository RecordRepository=Mockito.mock(RecordRepository.class);
//@自动连线
私人录音服务;
@以前
公共作废设置()
{
重置(记录存储库);
recordService=新的RecordServiceImpl(recordRepository);
}
@试验
公共void testFind()
{
Mockito.when(recordRepository.findOne(Mockito.anyString())。然后返回(null);
Record=recordService.find(“1”);
Assert.assertNull(记录);
验证(recordRepository,Mockito.times(1)).findOne(Mockito.eq(“1”));
}
@试验
公共void testSave()
{
Mockito.when(recordRepository.save(Mockito.any(Record.class)))
.thenAnswer(新答案)
{
@凌驾
公共记录应答(invocationMock调用)抛出