如何为自定义 OutputStream 编写单元测试
How to write unit test(s) for custom OutputStream
我必须创建一个 OutputStream
class(受 this 启发)写入记录器而不是 stdout
,所以我想出了以下:
case class OutputStreamLogger(level: Level) extends OutputStream {
val logger: Logger = org.slf4j.LoggerFactory.getLogger("OutputStreamLogger")
private var mem = ""
/**
* Writes byte to Logger, flushes automatically at EOL
*
* @param b Int Int representation of character to get written
*
* @return Unit
*/
def write(b: Int): Unit = {
// To prevent internal conversion from byte to int
val bytes = new Array[Byte](1)
// Get least significant byte from int argument
bytes(0) = (b & 0xff).toByte
// Turn byte array into String
mem += new String(bytes)
// Automatically flush at EOL
if(mem.endsWith("\n")) {
// Grab everything but newline
mem = mem.substring(0, mem.length - 1)
// Log it
flush()
}
}
/**
* Sends output bytes to logger at specified level
*
* @return Unit
*/
override def flush(): Unit = {
level match {
// Passing the format then the String eliminates
// need to check if logging at that level is enabled
case Level.TRACE => logger.trace("{}", mem)
case Level.DEBUG => logger.debug("{}", mem)
case Level.INFO => logger.info("{}", mem)
case Level.WARN => logger.warn("{}", mem)
case Level.ERROR => logger.error("{}", mem)
}
// Clear out buffer
mem = ""
}
}
我将如何对此进行单元测试?我查看了单元测试 OutputStream
s 的其他示例,但它们都使用 PrintStream
我想使用我的 OutputStreamLogger
并且似乎没有测试 [=16] =] 和 flush
方法
输出流的主要可测试性问题可能是这个声明:
val logger: Logger = org.slf4j.LoggerFactory.getLogger("OutputStreamLogger")
您已将记录器固定到一个具体的实例,无法自定义该实例的初始化。您现在可以在单元测试期间使用 slf4j 日志记录配置写入临时文件并读回。也许还有一个自定义附加程序可以写入内存缓冲区。
另一种可能性是更改该声明并允许在实例创建时使用记录器规范。然后您可以使用它来注入模拟记录器。
然后测试只是向输出流写入一些内容,然后查看换行符是否将输出刷新到记录器。
顺便说一句 - 您的实现看起来非常低效,因为它为写入的每个字节创建一个新字符串。而且有一个局部变量和一个同名的成员也很混乱。
我必须创建一个 OutputStream
class(受 this 启发)写入记录器而不是 stdout
,所以我想出了以下:
case class OutputStreamLogger(level: Level) extends OutputStream {
val logger: Logger = org.slf4j.LoggerFactory.getLogger("OutputStreamLogger")
private var mem = ""
/**
* Writes byte to Logger, flushes automatically at EOL
*
* @param b Int Int representation of character to get written
*
* @return Unit
*/
def write(b: Int): Unit = {
// To prevent internal conversion from byte to int
val bytes = new Array[Byte](1)
// Get least significant byte from int argument
bytes(0) = (b & 0xff).toByte
// Turn byte array into String
mem += new String(bytes)
// Automatically flush at EOL
if(mem.endsWith("\n")) {
// Grab everything but newline
mem = mem.substring(0, mem.length - 1)
// Log it
flush()
}
}
/**
* Sends output bytes to logger at specified level
*
* @return Unit
*/
override def flush(): Unit = {
level match {
// Passing the format then the String eliminates
// need to check if logging at that level is enabled
case Level.TRACE => logger.trace("{}", mem)
case Level.DEBUG => logger.debug("{}", mem)
case Level.INFO => logger.info("{}", mem)
case Level.WARN => logger.warn("{}", mem)
case Level.ERROR => logger.error("{}", mem)
}
// Clear out buffer
mem = ""
}
}
我将如何对此进行单元测试?我查看了单元测试 OutputStream
s 的其他示例,但它们都使用 PrintStream
我想使用我的 OutputStreamLogger
并且似乎没有测试 [=16] =] 和 flush
方法
输出流的主要可测试性问题可能是这个声明:
val logger: Logger = org.slf4j.LoggerFactory.getLogger("OutputStreamLogger")
您已将记录器固定到一个具体的实例,无法自定义该实例的初始化。您现在可以在单元测试期间使用 slf4j 日志记录配置写入临时文件并读回。也许还有一个自定义附加程序可以写入内存缓冲区。
另一种可能性是更改该声明并允许在实例创建时使用记录器规范。然后您可以使用它来注入模拟记录器。
然后测试只是向输出流写入一些内容,然后查看换行符是否将输出刷新到记录器。
顺便说一句 - 您的实现看起来非常低效,因为它为写入的每个字节创建一个新字符串。而且有一个局部变量和一个同名的成员也很混乱。