mockito 模拟实现接口的要测试的方法内的ResultSet的返回值

eoxn13cs  于 2022-11-08  发布在  其他
关注(0)|答案(2)|浏览(415)

我试图用Mockito模拟一些数据进行测试,但是我无法让它工作。我的问题是,我想模拟的值是我需要测试的方法中调用的返回值。
我有一个类MyAccessor.java(它实现了一个服务MyService.java),其中有一个方法getMyMethod(String value),在该方法中有一个对DB的调用:

final List<MyType> results = this.jdbcTemplate.query(sqlQuery, new RowMapper<MyType>() {
    @Override
    public MyType mapRow(final ResultSet rs, final int rowNum) throws SQLException {
        final int fieldA = rs.getInt("column_name_1");
        final int fieldB = rs.getInt("column_name_2");
        final int fieldC = rs.getInt("column_name_3");
        final int fieldD = rs.getInt("column_name_4");
        return new MyType(fieldA , fieldB , fieldC , fieldD);
    }
}, value);

有一种情况是由于数据库超时,rowMapper返回一个空列表。因此,在这种情况下,不可能执行return results.get(0),因为您将得到一个ArrayIndexOutOfBoundsException
于是我又查了一下:

if (!results.isEmpty()) {
    return results.get(0);
} else {
    return new MyType(0, 0, 0, 0);
}

现在,我想测试这个特定的场景,但是我不知道如何模拟resultSet返回,以便rowMapper返回一个空列表。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { ".....", "....."})
@TestPropertySource(".....")
public class MyClassTest {

    @Mock
    private JdbcTemplate jdbcTemplate;

    @InjectMocks
    @Autowired
    private MyService myService;

    @Before
    public void initMocks() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void myTestMethod() {
        Mockito.when(this.jdbcTemplate.query("SELECT NULL LIMIT 0", new RowMapper<Object>() {
            @Override
            public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new ArrayList<>();
            }
        })).thenReturn(new ArrayList<Object>());

        MyType result = this.myService.getMyMethod("value");
        assertEquals(0, result.getFieldA());
        assertEquals(0, result.getFieldB());
        assertEquals(0, result.getFieldC());
        assertEquals(0, result.getFieldD());
    }
}

但是测试失败了,因为返回的结果来自数据库,而不是空列表来测试超时情况。
我认为问题可能是因为我在服务接口而不是实现中注入了mock,但我想知道是否可以以某种方式完成,这样我就不必为该接口的每个实现测试mock。
或者,我可能使用了错误的Mockito框架,在这种情况下,我如何才能正确地测试?
注册。

rxztt3cl

rxztt3cl1#

我觉得你更想要的是:

@Test
public void myTestMethod() {
    Mockito.when(this.jdbcTemplate.query(eq("SELECT NULL LIMIT 0"), Mockito.any(RowMapper.class))
           .thenReturn(new ArrayList<Object>());
}

原因是,当你嘲笑的时候,你说只有当query的两个参数都和你定义的完全一样的时候才返回空列表。在你的例子中,你不关心RowMapper的确切示例。

jhdbpxl9

jhdbpxl92#

我发现了问题。我在接口中注入了mock,而不是在接口的实现中。所以我不得不改变:

@Mock
private JdbcTemplate jdbcTemplate;

@InjectMocks
@Autowired
private MyService myService;

至:

@Mock
private JdbcTemplate jdbcTemplate;

@InjectMocks
@Autowired
private MyAccessor myAccessor;

@Autowired
private MyService myService;

在测试中:

MyType result = this.myService.getMyMethod("value");

至:

MyType result = this.myAccessor.getMyMethod("value");

我不知道是否有更好的方法来实现这一点,而不必示例化服务可能具有的所有实现。
祝你好运

相关问题