有没有办法避免在 Spring 框架中创建大量接口和 类?
Is there a way to avoid creating huge amount of interfaces and classes in the Spring Framework?
我的开发模式如下:
- 我需要功能
- 我创建一个界面
- 我创建了一个实现该接口的空 class
- 我通过 TDD(使用 Mockito)构建实现,按照步骤 1 到 3 实现它所依赖的功能
这导致大量接口具有单一实现 classes。有没有捷径,更好的办法?
更新
根据评论我发现 Mockito 可以用来模拟 classes(不要笑我)。我做了一个小实验。这是 UML:
这里是相关代码(都是class,没有接口):
public class MessageGetter {
public String getMessage() {
return "Real Hello";
}
}
public class MessageDisplayer {
public void displayMessage(String message) {
System.out.println(message);
}
}
public class MessageWriter {
private MessageGetter messageGetter;
private MessageDisplayer messageDisplayer;
public void setMessageGetter(MessageGetter messageGetter) {
this.messageGetter = messageGetter;
}
public void setMessageDisplayer(MessageDisplayer messageDisplayer) {
this.messageDisplayer = messageDisplayer;
}
public void writeMessage() {
String message = messageGetter.getMessage();
messageDisplayer.displayMessage(message);
}
}
因此,使用 Mockito 我能够在没有单一界面的情况下测试 MessageWriter.writeMessage():
public class MessageWriterTest {
@Test
public void testWriteMessage() {
MessageGetter mockMessageGetter = mock(MessageGetter.class);
MessageDisplayer mockMessageDisplayer = mock(MessageDisplayer.class);
String mockMessage = "Mock Hello";
when(mockMessageGetter.getMessage()).thenReturn(mockMessage);
MessageWriter messageWriter = new MessageWriter();
messageWriter.setMessageGetter(mockMessageGetter);
messageWriter.setMessageDisplayer(mockMessageDisplayer);
messageWriter.writeMessage();
verify(mockMessageDisplayer).displayMessage(mockMessage);
}
}
我在 Spring Framework 中创建接口已经很长时间了,我不知道不这样做是否可以。可以停下来吗?
嗯,看起来使用 Spring 和 Mockito 生活可以更简单。我进一步简化了我在问题中发布的代码。基本思想是:
- 我们不需要 setter 方法
- 我们可以在单元测试中自动创建模拟
- 我们可以在单元测试中自动注入模拟
- 不需要接口
以下是此示例 pom.xml 中的依赖项:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
这是 2 个组件:
@Component
public class MessageDisplayer {
public void displayMessage(String message) {
System.out.println(message);
}
}
@Component
public class MessageGetter {
public String getMessage() {
return "Real Hello";
}
}
这是我正在测试的 class:
public class MessageWriter {
@Autowired
private MessageGetter messageGetter;
@Autowired
private MessageDisplayer messageDisplayer;
public void writeMessage() {
String message = messageGetter.getMessage();
messageDisplayer.displayMessage(message);
}
}
这是测试:
@RunWith(MockitoJUnitRunner.class)
public class MessageWriterTest {
@Mock
private MessageGetter mockMessageGetter;
@Mock
private MessageDisplayer mockMessageDisplayer;
@InjectMocks
private MessageWriter messageWriter;
@Test
public void testWriteMessage() {
String mockMessage = "Mock Hello";
when(mockMessageGetter.getMessage()).thenReturn(mockMessage);
messageWriter.writeMessage();
verify(mockMessageDisplayer).displayMessage(mockMessage);
}
}
我的开发模式如下:
- 我需要功能
- 我创建一个界面
- 我创建了一个实现该接口的空 class
- 我通过 TDD(使用 Mockito)构建实现,按照步骤 1 到 3 实现它所依赖的功能
这导致大量接口具有单一实现 classes。有没有捷径,更好的办法?
更新
根据评论我发现 Mockito 可以用来模拟 classes(不要笑我)。我做了一个小实验。这是 UML:
这里是相关代码(都是class,没有接口):
public class MessageGetter {
public String getMessage() {
return "Real Hello";
}
}
public class MessageDisplayer {
public void displayMessage(String message) {
System.out.println(message);
}
}
public class MessageWriter {
private MessageGetter messageGetter;
private MessageDisplayer messageDisplayer;
public void setMessageGetter(MessageGetter messageGetter) {
this.messageGetter = messageGetter;
}
public void setMessageDisplayer(MessageDisplayer messageDisplayer) {
this.messageDisplayer = messageDisplayer;
}
public void writeMessage() {
String message = messageGetter.getMessage();
messageDisplayer.displayMessage(message);
}
}
因此,使用 Mockito 我能够在没有单一界面的情况下测试 MessageWriter.writeMessage():
public class MessageWriterTest {
@Test
public void testWriteMessage() {
MessageGetter mockMessageGetter = mock(MessageGetter.class);
MessageDisplayer mockMessageDisplayer = mock(MessageDisplayer.class);
String mockMessage = "Mock Hello";
when(mockMessageGetter.getMessage()).thenReturn(mockMessage);
MessageWriter messageWriter = new MessageWriter();
messageWriter.setMessageGetter(mockMessageGetter);
messageWriter.setMessageDisplayer(mockMessageDisplayer);
messageWriter.writeMessage();
verify(mockMessageDisplayer).displayMessage(mockMessage);
}
}
我在 Spring Framework 中创建接口已经很长时间了,我不知道不这样做是否可以。可以停下来吗?
嗯,看起来使用 Spring 和 Mockito 生活可以更简单。我进一步简化了我在问题中发布的代码。基本思想是:
- 我们不需要 setter 方法
- 我们可以在单元测试中自动创建模拟
- 我们可以在单元测试中自动注入模拟
- 不需要接口
以下是此示例 pom.xml 中的依赖项:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
这是 2 个组件:
@Component
public class MessageDisplayer {
public void displayMessage(String message) {
System.out.println(message);
}
}
@Component
public class MessageGetter {
public String getMessage() {
return "Real Hello";
}
}
这是我正在测试的 class:
public class MessageWriter {
@Autowired
private MessageGetter messageGetter;
@Autowired
private MessageDisplayer messageDisplayer;
public void writeMessage() {
String message = messageGetter.getMessage();
messageDisplayer.displayMessage(message);
}
}
这是测试:
@RunWith(MockitoJUnitRunner.class)
public class MessageWriterTest {
@Mock
private MessageGetter mockMessageGetter;
@Mock
private MessageDisplayer mockMessageDisplayer;
@InjectMocks
private MessageWriter messageWriter;
@Test
public void testWriteMessage() {
String mockMessage = "Mock Hello";
when(mockMessageGetter.getMessage()).thenReturn(mockMessage);
messageWriter.writeMessage();
verify(mockMessageDisplayer).displayMessage(mockMessage);
}
}