java - 如何在 TestNG 中结合 Mockito 和 Spring

标签 java spring unit-testing mockito testng

我们正在构建一个使用 Spring Boot 的应用程序。我们使用 TestNG 和 Mockito 编写单元测试。然而,我发现编写when(...) 配置非常烦人,我想改用真正的组件。我开始使用 @Spy 组件而不是模拟,这工作得很好,直到我需要将 Spy 放入 Spy 中。如果可能的话,我想避免加载 Spring Context,因为上下文的创建非常慢,对于我来说加载最多 5 个类似乎有点过分了。

有什么办法,我如何使用真实的代码而不是 Mocks 并且不加载整个 Spring 上下文?或者我的方法根本错误,我应该模拟所有其他类然后测试类?

最佳答案

执行此操作的另一种方法(可能需要对代码进行一些修改)是通过构造函数注入(inject)而不是字段注入(inject)来完成。基本上消除了对 spring 上下文进行测试的任何需要。所以与其他答案相同

要测试的类

@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);
    }
}

测试用例

//@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();

    }
}

关于java - 如何在 TestNG 中结合 Mockito 和 Spring,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36328919/

相关文章:

java - 下载后如何刷新页面

java - org.hibernate.exception.ConstraintViolationException : Could not execute JDBC batch update

java - 打包构建 Spring 项目的最佳实践是什么?

spring - 使用Java JPA和Spring Data在MYSQL数据库中存储结构化注释

unit-testing - 我可以使用 Xcode Test Navigator 进行 EarlGrey 测试吗?

php - 模拟包装器时间函数

java - 如何编写一个程序来解决多个问题?

java - 澄清 - 在 Eclipse 中导入语句

spring - java.lang.NoClassDefFoundError : org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException

Django UrlResolver,在运行时添加 url 以进行测试