繁体   English   中英

Mocking 中的谓词 Java 使用 Mockito

[英]Mocking a Predicate in Java using Mockito

我有一个谓词,它检查数据库中是否存在行。我不确定这是否是谓词的好用法,但它使我的代码简洁明了。但是当我测试这段代码时,我无法模拟 DAO class不知道为什么会这样。

public class validator{

public Predicate<String> doesRowExists = fileName -> makeDao().isRowReturned(RowId);

  public AlertFileDAO makeDataDao(){
        return new DataDao();
    }

  public boolean validate(String RowId){
        return doesRowExists.test(rowId)
    }

}

//Test

public class ValidatorTest{

@setup
void beforeAll(){
  mockValidator = spy(new Validator());
  doReturn(mockDataDao)
                .when(mockValidator)
                .makeDataDao();
}

@Test
test_whenRowExists(){
new Validator.validate("1-abc-34");
}

当我触发测试时,它击中了实际的数据库,而不是使用模拟的 DAO class。我不确定我在这里究竟缺少什么。请建议。

为什么不简单地内联谓词并将 dao 作为构造函数参数传递? 这使您的 api 更清洁:谓词的方法调用与 getter 以及您最终得到的谓词的测试。

使用您接受的答案,用户必须使用以下内容:

validator.doesRowExist().test(rowId);

我相信以下内容会更容易使用:

validator.doesRowExist(rowId);

甚至:

validator.validate(rowId);

让我们进行一系列重构来实现这一目标:

步骤1:

您使用您的谓词来实现validate function。 没有其他调用,也没有传递给其他函数(接受谓词的高阶函数是它们的典型用途)。 让我们将谓词更改为方法:

public class Validator {

    public DataDao makeDataDao(){
        return new DataDao();
    }

    public boolean validate(String rowId){
        return doesRowExist(rowId);
    }

    private boolean doesRowExist(String rowId) {
        return makeDataDao().isRowReturned(rowId);
    }
}

第2步:

Daos 通常是单例(其中一个实例就足够了)。 根据您使用的框架,创建 Dao 可能比在其上调用方法的成本更高。 让我们应用依赖注入原则(类接收它的依赖,而不是创建它们):

public class Validator {

    private final DataDao dataDao;

    Validator(DataDao dataDao) {
        this.dataDao = dataDao;
    }

    public boolean validate(String rowId){
        return doesRowExist(rowId);
    }

    private boolean doesRowExist(String rowId) {
        return dataDao.isRowReturned(rowId);
    }
}

如果确实需要每次都创建 Dao,可以在构造函数中提供一个 fecory。

结果:

您的 class:

  • 有更好的 api
  • 可能更有效
  • 可以轻松测试:

@ExtendWith(MockitoExtension.class)
public class ValidatorTest {

    @Mock
    DataDao mockDataDao;

    @InjectMocks
    Validator validator;

    @Test
    void whenValidateReturnsValueFromIsRowReturned(){
        var rowId = "1-abc-34";
        doReturn(false)
                .when(mockDataDao)
                .isRowReturned(rowId);
        assertEquals(false, validator.validate(rowId));
    }

}

我将您的问题视为更常见任务的示例:如何存根字段 在您的情况下,您需要存根字段doesRowExists

通用任务有通用解决方案:使用 getter 代替public Predicate<String> getDoesRowExists() { return doesRowExists;}或者,使用通用代码样式, public Predicate<String> isRowExists() { return doesRowExists;}

因此,在您的生产代码中,您改为调用 getter 字段: return isRowExists().test(rowId)
在您的测试代码中,您只需模拟这个 getter: when(isRowExists).thenReturn(true)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM