如果我有一个很长的代码方法,它从 2 个或 3 个不同的来源收集数据并返回一个结果。我如何重构它以使其更易于单元测试?此方法是一个网络服务,我想从客户端代码进行一次调用以收集所有数据。
我可以将某些部分重构为更易于测试的更小方法。但当前方法仍将调用这 5 个方法,并且可测试性较低。假设 Java 作为编程语言,是否存在使此类代码可测试的模式?
最佳答案
这是一个非常常见的测试问题,我遇到的最常见的解决方案是将数据来源与使用依赖注入(inject)的数据的代码分开。这不仅支持良好的测试,而且在使用外部数据源时通常是一个很好的策略(良好的职责分离、隔离集成点、促进代码重用是其中的一些原因)。
您需要进行的更改如下:
- 对于每个数据源,创建一个接口(interface)来定义如何访问来自该源的数据,然后将返回数据的代码分解为一个单独的类来实现它。
- 依赖项将数据源注入(inject)到包含“长”函数的类中。
- 对于单元测试,注入(inject)每个数据源的模拟实现。
这里有一些代码示例展示了它的样子——请注意,这段代码只是模式的说明,您将需要一些更合理的名称。值得研究这种模式并了解更多有关依赖注入(inject)和模拟的信息 - 单元测试人员军械库中最强大的两种武器。
数据源
public interface DataSourceOne {
public Data getData();
}
public class DataSourceOneImpl implements DataSourceOne {
public Data getData() {
...
return data;
}
}
public interface DataSourceTwo {
public Data getData();
}
public class DataSourceTwoImpl implements DataSourceTwo {
public Data getData() {
...
return data;
}
}
长方法类
public class ClassWithLongMethod {
private DataSourceOne dataSourceOne;
private DataSourceTwo dataSourceTwo;
public ClassWithLongMethod(DataSourceOne dataSourceOne,
DataSourceTwo dataSourceTwo) {
this.dataSourceOne = dataSourceOne;
this.dataSourceTwo = dataSourceTwo;
}
public Result longMethod() {
someData = dataSourceOne.getData();
someMoreData = dataSourceTwo.getData();
...
return result;
}
}
单元测试
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ClassWithLongMethodTest {
@Test
public void testLongMethod() {
// Create mocked data sources which return the data required by your test
DataSourceOne dataSourceOne = mock(DataSourceOne.class);
when(dataSourceOne.getData()).thenReturn(...);
DataSourceTwo dataSourceTwo = mock(DataSourceTwo.class);
when(dataSourceTwo.getData()).thenReturn(...);
// Create the object under test using the mocked data sources
ClassWithLongMethod sut = new ClassWithLongMethod(dataSourceOne,
dataSourceTwo);
// Now you can unit test the long method in isolation from it's dependencies
Result result = sut.longMethod();
// Assertions on result
...
}
}
请原谅(并纠正)任何语法错误,这些天我写的 java 不多。
关于java - 我应该如何对长函数进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17708127/