[英]Mocking a Predicate in Java using Mockito
I have a Predicate which checks for a row existence in Database.I am not sure if this is a good use of predicate but it made my code clean and concise.But when I am Tesing this code I am not able to mock the DAO class and not sure why is the case.我有一个谓词,它检查数据库中是否存在行。我不确定这是否是谓词的好用法,但它使我的代码简洁明了。但是当我测试这段代码时,我无法模拟 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");
}
When Im triggering the test it is hitting the actual DB and not using the mocked DAO class.Im not sure what exactly I am missing here.Please suggest.当我触发测试时,它击中了实际的数据库,而不是使用模拟的 DAO class。我不确定我在这里究竟缺少什么。请建议。
Why don't you simply inline the predicate and deliver the dao as constructor argument?为什么不简单地内联谓词并将 dao 作为构造函数参数传递? This makes your api cleaner: method call vs getter for predicate and test on predicate you ended up with.这使您的 api 更清洁:谓词的方法调用与 getter 以及您最终得到的谓词的测试。
With your accepted answer, the user has to use the following:使用您接受的答案,用户必须使用以下内容:
validator.doesRowExist().test(rowId);
I believe the following would be easier to use:我相信以下内容会更容易使用:
validator.doesRowExist(rowId);
or even:甚至:
validator.validate(rowId);
Lets make a series of refactorings to achieve that:让我们进行一系列重构来实现这一目标:
Step 1:步骤1:
You use your predicate to implement validate
function.您使用您的谓词来实现validate
function。 There are no other calls, nor passing to another functions (higher-order functions accepting a predicate are a typical use for them).没有其他调用,也没有传递给其他函数(接受谓词的高阶函数是它们的典型用途)。 Let's change the predicate to a method:让我们将谓词更改为方法:
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);
}
}
Step 2:第2步:
Daos are typically singletons (one instance of them is enough). Daos 通常是单例(其中一个实例就足够了)。 Depending on the frameworks you use, creating a Dao may be more costly than calling a method on it.根据您使用的框架,创建 Dao 可能比在其上调用方法的成本更高。 Let's apply dependency injection principles (class receives it dependencies, not creates them):让我们应用依赖注入原则(类接收它的依赖,而不是创建它们):
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);
}
}
If you really need to create Dao each time, you can provide a fecory in the constructor.如果确实需要每次都创建 Dao,可以在构造函数中提供一个 fecory。
Result:结果:
Your class:您的 class:
@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));
}
}
I see your problem as example of more common task: how to stub a field .我将您的问题视为更常见任务的示例:如何存根字段。 In your case, you need to stub field doesRowExists
.在您的情况下,您需要存根字段doesRowExists
。
The common task has common solution: use getter instead : public Predicate<String> getDoesRowExists() { return doesRowExists;}
or, with common code style, public Predicate<String> isRowExists() { return doesRowExists;}
通用任务有通用解决方案:使用 getter 代替: public Predicate<String> getDoesRowExists() { return doesRowExists;}
或者,使用通用代码样式, public Predicate<String> isRowExists() { return doesRowExists;}
So, in your production code you call getter instead field: return isRowExists().test(rowId)
因此,在您的生产代码中,您改为调用 getter 字段: return isRowExists().test(rowId)
In your test code you just mock this getter: when(isRowExists).thenReturn(true)
在您的测试代码中,您只需模拟这个 getter: when(isRowExists).thenReturn(true)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.