我正在尝试对名为 StringReader 的 Java 对象进行行为测试。代码看起来像这样:
public interface CharReader {
public char readChar();
}
public class ByteArrayCharReader implements CharReader {
public ByteArrayCharReader(byte[] bytes);
public char readChar();
}
public class StringReader {
public String readString(byte[] bytes);
}
StringReader 的协议(protocol)/职责是:
- 当调用 readString 时,StringReader 应重复调用 CharReader.readChar() 从字节数组中读取字符,直到遇到空终止字符或最大字符数(20)。这个想法是 StringReader 不应该为正确的 unicode 字符解码中的所有组成部分而烦恼,这样的责任就委托(delegate)给了 CharReader。
我想为 StringReader 编写一个表达此协议(protocol)的单元测试,但我似乎不知道如何实现。
首先,我以为我只是希望 StringReader 在内部创建一个 ByteArrayCharReader 并在 readString() 中传递的字节数组上使用它,但这似乎没有意义,因为这样我就无法从外部模拟它.
看来我遇到了先有鸡还是先有蛋的问题。我想将 ByteArrayCharReader 注入(inject)到 StringReader 中,但是 ByteArrayCharReader 必须使用一个字节数组来构造,该数组仅在调用 readString 时才首先可用 - 那么如果我无法从外部构造/模拟它,我如何传递它?这似乎是一个愚蠢的问题,因为理论上我知道传递给 readString 的字节数组实际上来自 ByteArrayCharReader 也来自的测试,所以我确实已经准备好参数“在那里”。也许我错过了什么?
我应该提到,我正在开发遗留代码库,因此我无法轻松更改 StringReader.readString 的接口(interface)。
我有点沮丧,我不知道如何解决这个问题,因为这似乎是一个非常简单的场景; A 传递了一个数组并想要使用 ArrayParser 解析该数组 - 如何测试其行为(不是基于状态)?
最佳答案
您可以使用factory method pattern 。您只需注入(inject)工厂,而不是注入(inject)/实例化 ByteArrayCharReader ,该工厂的纯粹工作是提供所请求的读取器的实例:
public class ReadersFactoryImpl implements ReadersFactory {
public CharReader CreateByteReader(byte[] content) {
return new ByteArrayCharReader(content);
}
}
仅此而已。您可以轻松地模拟它并对其进行设置,以便它返回另一个模拟。测试 StringReader
是否按预期调用其他读取器应该足够了。
关于unit-testing - Mockist tdd : How to test UUT when collaborator can only be constructed inside UUT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9672889/