unit-testing - 单元测试原则
问题描述
当我编写单元测试时,我应该为我在源文件中创建的每个方法创建一个或多个测试方法吗?如果该方法调用了 3 个其他方法,是否应该模拟所有这些方法的响应?
解决方案
我相信你会得到很多不同的意见。但根据我的经验,通常每个公共方法至少要进行 1 次测试。我从快乐的路径开始,然后探索边缘情况和错误场景。我只模拟外部调用,私有方法可以通过公共方法测试,或者如果复杂,我要么将它们提取到可以独立测试的委托,要么放宽可访问性(即protected
在 Java 中)以便可以测试方法直接(基于敏感性/设计考虑的判断调用)。
在 Java / JUnit / Mockito 中:
public class SystemUnderTest {
private SomeDependency dependency;
public Response doSomething(String parameter) {
String foo = dependency.doSomethingForMe(parameter);
String bar = privateMethod(foo);
return new Response(bar);
}
private String privateMethod(String in) {
if("foo".equals(in)) return "bar";
else return "baz";
}
protected String complexNonPublicMethod(String a, String b, String c) {
.. does complicated things ..
}
}
public class SystemUnderTestTest { // Pardon the ugly name
@Mock
private SomeDependency dependencyMock;
@InjectMocks
private SystemUnderTest sut;
@Test
public void doSomething_happyPath() {
String input = "input";
String mockFoo = "foo";
when(dependencyMock.doSomethingForMe(input)).thenReturn(mockFoo);
String expected = new Response("bar");
String actual = sut.doSomething();
assertEquals(expected, actual); // JUnit syntax OR
assertThat(actual, is(expected)); // Hamcrest syntax (which I prefer)
verify(dependencyMock, times(1)).doSomethingForMe(input);
verifyNoMoreInteractions(dependencyMock);
}
@Test
public void doSomething_inputIsNull() {
String input = null;
String mockFoo = "foo";
when(dependencyMock.doSomethingForMe(input)).thenThrow(new NullPointerException("Input is required!"));
try {
sut.doSomething();
fail("Expected exception not thrown.");
} catch (Exception e) {
assertThat(e instanceof NullPointerException.class, is(true));
assertThat(e.getMessage, is("Input is required!"));
}
}
// Protected accessibility frees you from having to test this via some other public method
@Test
public void complexNonPublicMethod_happyPath() {
String expected = <whatever>;
String actual = sut.complexNonPublicMethod(a, b, c);
assertThat(actual, is(expected));
}
// Protected accessibility frees you from having to test this via some other public method
@Test
public void complexNonPublicMethod_NullInput_A() {
String expected = <whatever>;
String actual = sut.complexNonPublicMethod(null, b, c);
assertThat(actual, is(expected));
}
// Protected accessibility frees you from having to test this via some other public method
@Test
public void complexNonPublicMethod_NullInput_B() {
String expected = <whatever>;
String actual = sut.complexNonPublicMethod(a, null, c);
assertThat(actual, is(expected));
}
.. etc ..
}
祝你好运!
推荐阅读
- python - Pyinstaller:运行 .exe 文件时出现“ModuleNotFoundError:没有名为 'pyutil' 的模块”
- python - Project Euler #8:使用 numpy 计算子列表的乘积返回负值
- reactjs - 如何摆脱警告“React Hook useEffect has missing dependencies ...”同时(故意)保留一个空数组作为依赖项?
- typescript - 将对象数组转换为特定键的值数组
- javascript - Jest 无法测试等待的承诺,而是超时
- html - 使用 CSS 的子元素上带有浅黑色背景的不透明度
- python - 为什么即使更改格式化文本中的变量(Python),打印格式化文本也保持不变
- c++ - 为什么 Google Protobuf 在 Mac 上使用我的 cpp 应用程序执行
- python - 如何根据另一列中的值填充一列中的 NaN?
- r - 参数 C 是否无法针对“nu-svr”进行优化,还是错误?