喜 我创建了一个类,其中有一个构造函数,如下所示:
public class ABC {
private static String host;
private static String port;
private static String browser;
private static String url;
private static String fullurl;
public ABC(){
try {
File file = new File("Element.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
请告诉我构造函数的测试用例:
答案 0 :(得分:1)
我不知道你需要什么样的测试用例。 但是,您可以通过以下方式验证最终结果:提供xml并声明有关host,port,browser,url,fullurl的值。
也许您需要重构它以通过测试用例创建xml文本或文件集。
答案 1 :(得分:1)
首先,doc
不是输出。它是构造函数中的局部变量,无法在单元测试中进行测试/验证。但另一方面,您可以依赖(经过测试的)Parser。它将为给定的输入文件生成正确的DOM。
如果输入文件中的值存储到指定的字段中,您可能需要测试。
因此,创建一个包含合法值的输入文件,创建一个实例并断言字段是否包含正确的值:
@Test
public void testABCWithLegalValues() {
ABC abc = new ABC("correct.xml"); // NOTE! I invented a new constructor
// to allow passing test config files!!
assertEquals("www.google.com", abc.getHost());
assertEquals(80, abc.getPort());
// ...
}
这是基于jUnit 4的示例测试方法。
其他测试会向构造函数提供格式错误的xml文件或包含非法数据的文件(如端口地址> 65535),并验证该类是否按指定做出反应。
答案 2 :(得分:1)
您的班级正在执行两项不同的任务:
由于目前这一切都发生在构造函数中,并且文件名是硬编码的,因此这个类很难进行单元测试。
如果你可以修改课程,那么我的建议就是让这个课程可以测试:
不要硬编码要解析的文件的名称。我会在这里将它作为构造函数参数传递,因为您以后不需要fileName,因此无需将其保留为私有字段。
分离任务,让构造函数读取文件并创建一个单独的方法来处理文档。
由于您需要codez,因此这里是修改后的类:
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class ABC {
private static final Logger LOG = Logger.getLogger(ABC.class);
private static final String DEFAULT_FILENAME = "Element.xml";
private String host;
private String port;
private String browser;
private String url;
private String fullurl;
public class AbcFileAccessException extends Exception {
private static final long serialVersionUID = 1L;
public AbcFileAccessException(Exception e) {
super(e);
}
}
public ABC() throws AbcFileAccessException {
this(DEFAULT_FILENAME);
}
public ABC(String fileName) throws AbcFileAccessException {
File file = new File(fileName);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
process(db.parse(file));
} catch (ParserConfigurationException e) {
throw new AbcFileAccessException(e);
} catch (SAXException e) {
throw new AbcFileAccessException(e);
} catch (IOException e) {
throw new AbcFileAccessException(e);
}
}
public ABC(Document document) {
process(document);
}
public void process(Document document) {
if (document == null) {
throw new IllegalArgumentException("Document may not be null");
}
document.getDocumentElement().normalize();
LOG.info("Root element " + document.getDocumentElement().getNodeName());
NodeList nodeLst = document.getElementsByTagName("selenium");
for (int s = 0; s < nodeLst.getLength(); s++) {
Node fstNode = nodeLst.item(s);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElmnt = (Element) fstNode;
NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("name");
Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
NodeList fstNm = fstNmElmnt.getChildNodes();
String name = ((Node) fstNm.item(0)).getNodeValue();
NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("value");
Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
NodeList lstNm = lstNmElmnt.getChildNodes();
String value = ((Node) lstNm.item(0)).getNodeValue();
if (name.equals("host")) {
host = value;
}
if (name.equals("port")) {
port = value;
}
if (name.equals("browser")) {
browser = value;
}
if (name.equals("url")) {
url = value;
}
if (name.equals("fullurl")) {
fullurl = value;
}
}
}
}
public String getHost() {
return host;
}
public String getPort() {
return port;
}
public String getBrowser() {
return browser;
}
public String getUrl() {
return url;
}
public String getFullurl() {
return fullurl;
}
}
我做的其他改进:
避免像这样运行时数据的静态字段。如果它们是私有的(如在您的示例中)那么它们可以只是实例字段,看到您已经在创建类的(非单例)实例。如果你打算让它们被其他类访问,那就更糟了,因为那些其他类可以访问像ABC.host
这样的字段,这使得它们难以测试并锁定在你的实现类中。我们现在不要进入( - :
永远不要从构造函数中调用setter(请参阅http://www.javapractices.com/topic/TopicAction.do?Id=215获取解释)。
范围try-catch块尽可能窄(或实际)。这使得您的代码更具可读性,因为它可以清楚地抛出异常。
分别捕获每个异常类型。将它们组合在一起会使代码的可读性降低。我同意这对API的某些部分来说是一种痛苦(尝试使用反射),但这是一种很好的做法。假设开发人员应该能够从打印输出中读取和理解您的代码(因此不需要IDE的悬停和代码导航功能)。
不要通过调用printStacktrace来处理异常,记录错误或抛出RuntimeException(如果可以避免)。如果这样做,至少要彻底记录这些错误情况。可以为错误条件创建自己的异常类型,这使得API非常容易理解(因此其他开发人员不必深入研究您的代码,但可以在阅读JavaDoc后使用该类)。
不要使用System.out.println进行日志记录,请使用Log4j之类的日志框架。
现在可以按如下方式测试该类:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import xcon.pilot.ABC.AbcFileAccessException;
public class ABCTest {
private Document document;
@Before
public void setUp() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
}
@Test
public void testProcess() throws ParserConfigurationException,
AbcFileAccessException, TransformerFactoryConfigurationError,
TransformerException {
Element root = (Element) document.createElement("root");
document.appendChild(root);
String host = "myhost";
String port = "myport";
String browser = "mybrowser";
String url = "myurl";
String fullurl = "myfullurl";
root.appendChild(createElement("host", host));
root.appendChild(createElement("port", port));
root.appendChild(createElement("browser", browser));
root.appendChild(createElement("url", url));
root.appendChild(createElement("fullurl", fullurl));
// for your convenience
printXml();
ABC instance = new ABC(document);
Assert.assertEquals(host, instance.getHost());
Assert.assertEquals(port, instance.getPort());
Assert.assertEquals(browser, instance.getBrowser());
Assert.assertEquals(url, instance.getUrl());
Assert.assertEquals(fullurl, instance.getFullurl());
}
private Element createElement(String name, String value) {
Element result = (Element) document.createElement("selenium");
Element nameElement = document.createElement("name");
nameElement.setTextContent(name);
result.appendChild(nameElement);
Element valueElement = document.createElement("value");
valueElement.setTextContent(value);
result.appendChild(valueElement);
return result;
}
private void printXml() throws TransformerConfigurationException,
TransformerFactoryConfigurationError, TransformerException {
Transformer transformer = TransformerFactory.newInstance()
.newTransformer();
Source source = new DOMSource(document);
Result output = new StreamResult(System.out);
transformer.transform(source, output);
}
}
这会测试您的文档处理逻辑。测试文件的读取和解析是非常棘手的,并不能真正被视为单元测试,因为您始终依赖于操作系统及其文件系统。我通常将其作为集成测试和构建/部署支持的一部分。它有助于在代码中建立良好的健全性检查和错误处理,从而清楚地及早地报告丢失/不正确的文件。
希望这有助于你。