java Mockito验证抽象方法
java Mockito verify abstract method
我在验证对测试中 class 方法的调用时遇到问题,使用 verify() 方法它告诉该方法未完成调用,此方法在 super 中定义为抽象class (加载文件(字符串))
找到下面的代码:
public abstract class FileParser {
public Iterator<String> loadFile(FileSettingsToSend fileSetting) {
System.out.println("file before staged");
try {
if(!movFile("staged",fileSetting))
return null;
System.out.println("file after move "+fileSetting.getFile().getAbsolutePath());
boolean isValidFormatFile = fileValidator.checkFileFormat(fileSetting);
if (!isValidFormatFile) {
System.out.println("file format is not valid");
return null;
}
return readBlock(fileSetting);
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
} finally {
}
//return null;
}
public abstract Iterator<String> readBlock(FileSettingsToSend fileSettingsToSend)
throws JsonProcessingException, IOException;
}
public class JsonFileParser extends FileParser {
public final ObjectMapper mapper = new ObjectMapper();
@Autowired
public JsonFileParser(FileValidator jsonFileValidatorService, FileAttributeService fileAttributeService) {
super(jsonFileValidatorService, fileAttributeService);
}
@Override
public Iterator<String> readBlock(FileSettingsToSend fileSetting) throws JsonProcessingException, IOException {
ObjectMapper mapper = new ObjectMapper();
System.out.println("inside readBlock json implementation");
List<String> listAttribute = fileAttributeService.getAttributes(fileSetting.getDiretoryPath());
String[] blocDelimitor = fileAttributeService.getDelimitorRepositpry(fileSetting.getDiretoryPath());
System.out.println("after validator");
final JsonNode root = mapper.readTree(fileSetting.getFile());
if (root == null)
return null;
Iterator<JsonNode> nodeIterator = root.elements();
System.out.println("Data is " + root);
return new Iterator<String>() {
JsonNode node;
@Override
public boolean hasNext() {
return nodeIterator.hasNext();
}
@Override
public String next() {
int i = 0;
node = nodeIterator.next();
System.out.println("after nex " + node.toString());
Arrays.stream(blocDelimitor).forEach(e -> {
node = node.path(e);
System.out.println("inside next " + node.toString());
});
String result = null;
if (node.isArray()) {
System.out.println("It is Array");
for (JsonNode node1 : node) {
if (i != 0)
result = result + "," + listAttribute.stream().map(e -> e + "=" + node1.get(e))
.collect(Collectors.joining(","));
else
result = listAttribute.stream().map(e -> e + "=" + node1.get(e))
.collect(Collectors.joining(","));
i++;
}
} else
result = listAttribute.stream().map(e -> e + "=" + node.get(e)).collect(Collectors.joining(","));
return result;
}
};
}
测试方法是:
@Mock
FileValidator jsonFileValidatorService;
@Mock
FileAttributeService fileAttributeService;
JsonFileParser jsonFileParserMock = new JsonFileParser(jsonFileValidatorService, fileAttributeService);
@Test
public void validatorNotTrue() throws JsonProcessingException, IOException{
when(jsonFileValidatorService.checkFileFormat( anyObject() )).thenReturn(true);
JsonFileParser jsonFileParser = Mockito.spy(jsonFileParserMock);
doReturn(true).when(jsonFileParser).movFile(anyString(),anyObject() );
assertNull(jsonFileParser.loadFile(null));
verify(jsonFileParser, times(1)).movFile(anyString(),anyObject());
assertTrue(jsonFileParser.movFile(anyString(), anyObject()));
assertTrue(jsonFileValidatorService.checkFileFormat( anyObject() ));
//exception.expect(Exception.class);
verify(jsonFileParser,times(1)).readBlock(anyObject();
}
@BeforeClass
public static void settingUp(){
}
@Before
public void initMock(){
MockitoAnnotations.initMocks(this);
}
行 verify(jsonFileParser,times(1)).readBlock(anyObject(); return false; 意思是 jsonfileParser 的 loadFile 方法没有被调用
你能告诉你为什么不叫它吗?
谢谢。
发生这种情况是因为您在创建 JsonFileParser
之后初始化模拟。请注意,@Before
方法在您的测试 class 的所有字段都初始化后执行。
因此,您将 null
依赖项传递给 class。对 null
FileValidator
的调用抛出 NullPointerException
,但您在 catch 块中吞下了它。
通常建议验证您传递给构造函数和方法的参数,以便在出现错误时快速失败。例如,Java 附带了一个方便的 Objects::requireNonNull 方法来验证传递的参数是否为非空。
同样,吞下每一个异常通常是一种不好的做法。例如,在您的示例中,您希望 IOException
和 JsonProcessingException
被抛出。最好明确地捕获这些并让程序为任何其他程序崩溃(或至少记录警告)。
最后,模拟和间谍很容易被过度使用。通常,使用伪造就足够了——你的接口的虚拟实现。根据您对代码的控制程度,您可能还想重构它以避免使用间谍。在您可以自由更改的代码中使用一个可能表示架构问题。
我在验证对测试中 class 方法的调用时遇到问题,使用 verify() 方法它告诉该方法未完成调用,此方法在 super 中定义为抽象class (加载文件(字符串))
找到下面的代码:
public abstract class FileParser {
public Iterator<String> loadFile(FileSettingsToSend fileSetting) {
System.out.println("file before staged");
try {
if(!movFile("staged",fileSetting))
return null;
System.out.println("file after move "+fileSetting.getFile().getAbsolutePath());
boolean isValidFormatFile = fileValidator.checkFileFormat(fileSetting);
if (!isValidFormatFile) {
System.out.println("file format is not valid");
return null;
}
return readBlock(fileSetting);
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
} finally {
}
//return null;
}
public abstract Iterator<String> readBlock(FileSettingsToSend fileSettingsToSend)
throws JsonProcessingException, IOException;
}
public class JsonFileParser extends FileParser {
public final ObjectMapper mapper = new ObjectMapper();
@Autowired
public JsonFileParser(FileValidator jsonFileValidatorService, FileAttributeService fileAttributeService) {
super(jsonFileValidatorService, fileAttributeService);
}
@Override
public Iterator<String> readBlock(FileSettingsToSend fileSetting) throws JsonProcessingException, IOException {
ObjectMapper mapper = new ObjectMapper();
System.out.println("inside readBlock json implementation");
List<String> listAttribute = fileAttributeService.getAttributes(fileSetting.getDiretoryPath());
String[] blocDelimitor = fileAttributeService.getDelimitorRepositpry(fileSetting.getDiretoryPath());
System.out.println("after validator");
final JsonNode root = mapper.readTree(fileSetting.getFile());
if (root == null)
return null;
Iterator<JsonNode> nodeIterator = root.elements();
System.out.println("Data is " + root);
return new Iterator<String>() {
JsonNode node;
@Override
public boolean hasNext() {
return nodeIterator.hasNext();
}
@Override
public String next() {
int i = 0;
node = nodeIterator.next();
System.out.println("after nex " + node.toString());
Arrays.stream(blocDelimitor).forEach(e -> {
node = node.path(e);
System.out.println("inside next " + node.toString());
});
String result = null;
if (node.isArray()) {
System.out.println("It is Array");
for (JsonNode node1 : node) {
if (i != 0)
result = result + "," + listAttribute.stream().map(e -> e + "=" + node1.get(e))
.collect(Collectors.joining(","));
else
result = listAttribute.stream().map(e -> e + "=" + node1.get(e))
.collect(Collectors.joining(","));
i++;
}
} else
result = listAttribute.stream().map(e -> e + "=" + node.get(e)).collect(Collectors.joining(","));
return result;
}
};
}
测试方法是:
@Mock
FileValidator jsonFileValidatorService;
@Mock
FileAttributeService fileAttributeService;
JsonFileParser jsonFileParserMock = new JsonFileParser(jsonFileValidatorService, fileAttributeService);
@Test
public void validatorNotTrue() throws JsonProcessingException, IOException{
when(jsonFileValidatorService.checkFileFormat( anyObject() )).thenReturn(true);
JsonFileParser jsonFileParser = Mockito.spy(jsonFileParserMock);
doReturn(true).when(jsonFileParser).movFile(anyString(),anyObject() );
assertNull(jsonFileParser.loadFile(null));
verify(jsonFileParser, times(1)).movFile(anyString(),anyObject());
assertTrue(jsonFileParser.movFile(anyString(), anyObject()));
assertTrue(jsonFileValidatorService.checkFileFormat( anyObject() ));
//exception.expect(Exception.class);
verify(jsonFileParser,times(1)).readBlock(anyObject();
}
@BeforeClass
public static void settingUp(){
}
@Before
public void initMock(){
MockitoAnnotations.initMocks(this);
}
行 verify(jsonFileParser,times(1)).readBlock(anyObject(); return false; 意思是 jsonfileParser 的 loadFile 方法没有被调用 你能告诉你为什么不叫它吗? 谢谢。
发生这种情况是因为您在创建 JsonFileParser
之后初始化模拟。请注意,@Before
方法在您的测试 class 的所有字段都初始化后执行。
因此,您将 null
依赖项传递给 class。对 null
FileValidator
的调用抛出 NullPointerException
,但您在 catch 块中吞下了它。
通常建议验证您传递给构造函数和方法的参数,以便在出现错误时快速失败。例如,Java 附带了一个方便的 Objects::requireNonNull 方法来验证传递的参数是否为非空。
同样,吞下每一个异常通常是一种不好的做法。例如,在您的示例中,您希望 IOException
和 JsonProcessingException
被抛出。最好明确地捕获这些并让程序为任何其他程序崩溃(或至少记录警告)。
最后,模拟和间谍很容易被过度使用。通常,使用伪造就足够了——你的接口的虚拟实现。根据您对代码的控制程度,您可能还想重构它以避免使用间谍。在您可以自由更改的代码中使用一个可能表示架构问题。