-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3e910dd
commit 9a3464b
Showing
2 changed files
with
187 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
--- | ||
category: | ||
- 笔记 | ||
- backend | ||
- code-snippets | ||
tag: | ||
- java | ||
--- | ||
|
||
# DBUnit 相关代码片段 | ||
|
||
## 根据不同连接创建不同的数据库连接 | ||
|
||
```java | ||
private IDatabaseConnection createDatabaseConnection(Connection conn, String schema) { | ||
IDatabaseConnection dbUnitConn = new DatabaseConnection(conn, schema); | ||
DatabaseConfig config = dbUnitConn.getConfig(); | ||
config.setProperty(DatabaseConfig.PROPERTY_ESCAPE_PATTERN, "\"?\""); | ||
config.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FILEDS, true); | ||
|
||
String dbName = conn.getMetaData().getDatabaseProductName().toLowerCase(); | ||
if (dbName.contains("oracle")) { | ||
// 注意这里没有使用 OracleDataTypeFactory, 而是自己的 MyOracleDataTypeFactory | ||
config.setProperty(DatabaseConfig.PROPERTY_DATETYPE_FACTORY, new MyOracleDataTypeFactory()); | ||
} else if (dbName.contains("mysql")) { | ||
config.setProperty(DatabaseConfig.PROPERTY_DATETYPE_FACTORY, new MySqlDataTypeFactory()); | ||
config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler()); | ||
} | ||
} | ||
``` | ||
|
||
## 自定义数据类型 | ||
|
||
如果想做特殊处理的话,自定义 `DataType`, 然后注册到 `DataTypeFactory`。 | ||
|
||
比如,对于 Oracle 数据库的 `CHAR` 类型,预期值跟实际值比较时,忽略空格后比较。 | ||
可以自定义 DataType 来实现。 | ||
|
||
### 自定义字符串数据类型 | ||
|
||
```java | ||
public class StringDataTypeIgnoreSpaceDataType extends StringDataType { | ||
public StringDataTypeIgnoreSpaceDataType(String name, int sqlType) { | ||
super(name, sqlType); | ||
} | ||
|
||
@Override | ||
protected int compareNonNulls(Object value1, Object value2) throws TypeCastException { | ||
String val1 = (String) value1; | ||
String val2 = (String) value2; | ||
|
||
return val1.strip().compareTo(val2.strip()); | ||
} | ||
} | ||
``` | ||
|
||
### 注册到数据类型工厂 | ||
|
||
```java | ||
|
||
public class MyOracleDataTypeFactory extends OracleDataTypeFactory { | ||
|
||
// 第二个参数的 sqlType 跟原来的 sqlType 保持一致 | ||
public static final DataType MY_CHAR = new StringDataTypeIgnoreSpaceDataType("CHAR", 1); | ||
public static final DataType MY_NCHAR = new StringDataTypeIgnoreSpaceDataType("NCHAR", -15); | ||
|
||
@Override | ||
public DataType createDataType(int sqlType, String sqlTypeName) throws DataTypeException { | ||
if ("CHAR".equals(sqlTypeName)) { | ||
return MY_CHAR; | ||
} else { | ||
return super.createDataType(sqlType, sqlTypeName); | ||
} | ||
} | ||
|
||
} | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
--- | ||
category: | ||
- 笔记 | ||
- backend | ||
- code-snippets | ||
tag: | ||
- java | ||
--- | ||
|
||
# Mockito 相关代码片段 | ||
|
||
## 参数验证 | ||
|
||
JUnit 测试时,对应 Mocked 方法,我们可以返回自己想要的返回值或异常,但是有时希望验证一下,我们调用时传的参数是否正确。 | ||
|
||
此时,可以使用 ArgumentCaptor 来收集参数,进而做验证。 | ||
|
||
示例: | ||
|
||
```java | ||
ArgumentCaptor<TestIn> argCaptor = ArgumentCaptor.forClass(TestIn.class); | ||
// 调用 (注意,这里指定了类型,不指定的话有些时候不能正确执行,比如, dao.find(any()) 就不知实际该匹配哪个,可能返回 null) | ||
testService.doMethod(any(TestIn.class)).thenReturn(1); | ||
// 参数收集 | ||
verify(testService).doMethod(argCaptor.captor()); | ||
// 参数校验 | ||
assertEquals("0", argCaptor.getValue().getInArg()); | ||
``` | ||
|
||
多次调用时的验证: | ||
|
||
```java | ||
ArgumentCaptor<TestIn> argCaptor = ArgumentCaptor.forClass(TestIn.class); | ||
|
||
// 参数收集 | ||
verify(testService, times(2)).doMethod(argCaptor.captor()); | ||
List<TestIn> inValues = argCaptor.getAllValues(); | ||
|
||
// 参数校验 | ||
// 第一次调用的参数验证 | ||
assertEquals("0", inValues.get(0).getInArg()); | ||
// 第二次调用的参数验证 | ||
assertEquals("1", inValues.get(1).getInArg()); | ||
``` | ||
|
||
## 编程式返回期待值 | ||
|
||
```java | ||
when(testService.doMethod(any())).thenAnswer(inv -> { | ||
TestIn in = inv.getArgument(0, TestIn.class); | ||
TestOut out = new TestOut(); | ||
|
||
out.setA(in.getA()); | ||
if ("".equals(in.getB())) { | ||
out.setOb("1"); | ||
} | ||
|
||
return out; | ||
}); | ||
|
||
when(testService.doMethod2(eq("1"), any())).thenReturn("0"); | ||
``` | ||
|
||
## 参数为对象时,返回 null (无法正确匹配) | ||
|
||
当参数为对象类型时,为了能区分不太的参数,返回不同的内容,需要自定义参数匹配来实现。 | ||
单纯的用 `any(InParam.class)` 是无法实现的。 | ||
|
||
自定义参数匹配示例: | ||
|
||
```java | ||
public class MessageMatcher implements ArgumentMatcher<Message> { | ||
|
||
private Message left; | ||
|
||
// constructors | ||
|
||
@Override | ||
public boolean matches(Message right) { | ||
return left.getFrom().equals(right.getFrom()) && | ||
left.getTo().equals(right.getTo()) && | ||
left.getText().equals(right.getText()) && | ||
right.getDate() != null && | ||
right.getId() != null; | ||
} | ||
} | ||
``` | ||
|
||
使用: | ||
|
||
```java | ||
// 业务代码 | ||
MessageDTO messageDTO = new MessageDTO(); | ||
messageDTO.setFrom("me"); | ||
messageDTO.setTo("you"); | ||
messageDTO.setText("Hello, you!"); | ||
|
||
messageController.createMessage(messageDTO); | ||
|
||
// JUnit 代码 | ||
Message message = new Message(); | ||
message.setFrom("me"); | ||
message.setTo("you"); | ||
message.setText("Hello, you!"); | ||
|
||
verify(messageService, times(1)).deliverMessage(argThat(new MessageMatcher(message))); | ||
``` | ||
|
||
关于自定义参数匹配,可以参考这篇文章: [Mockito ArgumentMatchers](https://www.baeldung.com/mockito-argument-matchers)。 |