【发布时间】:2021-04-21 13:41:07
【问题描述】:
在 Spring/Spring Boot 中编程时,通常的做法是让每个服务/组件实现一个接口,例如:
public interface IAdder {
int add(int a, int b);
}
@Service
public class Adder implements IAdder {
public int add(int a, int b) { return a + b; }
}
如果我不打算为“Adder”功能实现多个实现,为什么我实际上需要编写该接口?
该问题的一个常见答案是“您将需要它来模拟您的单元测试”。对此,我可以回答——不是真的。我可以使用您能想到的所有可能的模拟框架(例如 Mockito)来模拟加法器:
@Autowired
IMultiplier multiplier; // Class under test
@Mock
IAdder adder;
@Test // Assuming I implement multiplication by multiple additions
public void multiplicationTest() {
// Arrange
when(adder).add(3, 3).thenReturn(6);
// Act
int result = multiplier.multiply(3, 5);
// Assert
verify(adder, times(4)).add(3, 3);
assertThat(result).isEqualTo(15);
}
说了这么多,IAadder接口能给我带来什么好处呢?
【问题讨论】:
-
@Stultuske 我确实听说过这个概念,但我试图在这里应用一些批判性思维并挑战我认为没有任何用处的范式。
-
虽然几乎总是存在增量优势,但并不总是立即获得巨大优势,其中之一就是测试/DI/IoC/等。在 Spring Boot 中,接口用于代理生成——这并不意味着 everything 需要代理;这取决于它的使用方式(以及框架使用的方式)。不相关,但我将接口命名为
Adder,并根据它们的详细信息命名实现。整个I前缀在不久前就在Java 中死掉了。 -
“只要你有选择,JDK动态代理是首选”根据该链接。有人知道为什么会这样吗?
-
@DaveNewton "TESTING" 请全部大写。这使得使用 Spring 进行测试变得轻而易举。在编码了 15 年并偶尔在春季成为提交者之后,这是我的第一选择。
-
虽然接口可能很有用,但我认为这个问题是在询问每个服务层类上的接口。
标签: java spring spring-boot unit-testing