我是否应该在实际课程中重复代码
我想测试一个特定的方法是否会产生预期的结果,但要做到这一点,我还需要在测试中操作输入。我是否应该在实际课程中重复代码
class ToTest {
public String produceResponse(String input) {
// ....
encryptedIds = encryptIds(input)
output = doStuff(input, encryptedIds)
}
public encryptIds(input) {
....
}
}
在我的测试中,我需要检查produceResponse实际上是否产生预期的响应。 为了做到这一点,我必须加密输入中的ID。
我的问题是:我应该在测试中重写encryptIds(这样我就可以有更多的控制器)或者我应该从类本身调用encryptIds。
有没有更好的方法来解决这个问题?我不喜欢我的测试,我知道特定流程会发生什么。
如果我理解正确,你想测试produceResponse()
已知encryptedIds作为输入。
你可以做,没有重构的代码,但它很可能是一个好主意,重构它,所以这就是我要解释一下:
class ToTest {
private IdEncryptor encryptor;
public ToTest(IdEncryptor encryptor) {
this.encryptor = encryptor;
}
public String produceResponse(String input) {
String[] encryptedIds = encryptor.encryptIds(input);
return doStuff(input, encryptedIds);
}
}
现在,您可以单元测试IdEncryptor到测试它是否会根据字符串输入生成正确的加密ID。
要测试ToTest类,您可以模拟IdEncryptor,以便无论接收到什么输入,它都会生成您想要的encryptedIds。例如与mockito:
IdEncryptor mockEncryptor = mock(IdEncryptor.class);
when(mockEncryptor.encryptIds(any(String.class)).thenReturn(new String[] {"a", "b"});
ToTest toTest = new ToTest(mockEncryptor);
String response = toTest.produceResponse("input");
// expect that the response is what you expect given "a", "b" as input of doStuff()
- 切勿将任何生产代码复制到单元测试中,因为它会在某个时间点过期。
-
如果这两种方法是公开的,他们是公共API的一部分,所以:
- 你应该先单元测试
encryptIds(String)
方法 - 然后单元测试
produceResponse(String)
方法的正确行为,将内部使用已经测试encryptIds(String)
方法
- 你应该先单元测试
-
如果
encryptIds(String)
不会是公共API的一部分:- 那么它是内部实现和辅助方法,是不是可以进行单元测试
-
produceResponse(String)
然后用于加密的副作用负责:- 你仍然可以测试它,如果你将其标记包专用(无改性剂)
- 你也可以改变
encryptIds(String)
实施仅用于测试目的
是加密id的东西是不可或缺的东西是你的系统?就目前而言,这门课程需要一些输入并产生一些输出,并且就您的测试而言,这是重要的,不多也不少。
不执行加密的影响是什么?如果你的doStuff
方法如果没有发生就会失败,那么它就是你的待测类的内部细节,我根本就不会关心它。如果这是绝对必须执行的步骤,那么我会重构代码以验证它绝对发生了,也许使用@ jb-nizet的模拟回答。
至于重复生产代码测试,@Crazyjavahacking说,你不应该这样做的一般情况,但我必须使用带有没有问题生产代码从测试 - 也许不是在单元级,但绝对是比我更高的系统,例如当测试写入数据库时,我将使用读取代码来验证它是否正确发生,但也将有独立测试来验证读取路径以及
如果encryptIds不是API的一部分,该怎么办? – user844541
增加了更多描述 – Crazyjavahacking