如何使用 Postgresql 后端对 DataSource 上的连接失败进行单元测试?
How do I unit test connection failures on a DataSource with Postgresql backend?
为了在数据库中断期间测试 Web 服务的行为,我想在我的单元测试中模拟连接失败。数据库后端是 Postgresql,代码使用了一些非标准的 SQL 查询,这使得很难使用普通的内存数据库进行测试。可以通过 DataSource 访问数据库连接,该 DataSource 将连接管理推迟到 ConnectionPool。
如何在单元测试中模拟 temporary/intermitent 数据库断开连接以验证正确的错误处理和从连接中断中恢复?
如@duffymo 所述,模拟是可行的方法。
如果您真的要进行单元测试,您已经会使用由模拟框架创建的模拟,因为单元测试需要隔离个体将 dependencies 替换为 test doubles 的单位。模拟框架是创建此类 测试替身 的最简单和最稳定的方法。
但我猜你是在用 UnitTesting Framework 执行 Integration Tests,称它们为 "unit tests"原因。
然而..
由于您的测试依赖于数据源的实际功能,因此 spy 将是一个不错的选择,如下所示:
class DatasourceUsageTest{
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void reportDatabaseOutage(){
// arrange
DataSource myDatasource = aquireDatasourceSomehow();
DataSource spyOfMyDatasource = Mockito.spy(myDatasource);
Mockito.doCallRealMethod() // first call
.doThrow(new SqlException("Report this message") // second call (and all following)
.when(spyOfMyDatasource).methodExpectedToFail();
SomeType testedUnit = createUnitAndInject(spyOfMyDatasource );
// act call #1
testedUnit.theMethodUsingDatasource();
Mockito.verify(spyOfMyDatasource).methodExpectedToFail();
// act call #2
exception.expect(TheExceptionTypeToBeThrown.class);
exception.expectMessage(EXCEPTION_MESSAGE_PREFIX + "Report this message");
testedUnit.theMethodUsingDatasource();
// Code below this will not be executed
}
}
这里的问题(与任何 集成测试 一样)是您的数据库可能有一个真正的问题,在这种情况下,此测试在调用 #1 时失败(因此原因错误).
为了在数据库中断期间测试 Web 服务的行为,我想在我的单元测试中模拟连接失败。数据库后端是 Postgresql,代码使用了一些非标准的 SQL 查询,这使得很难使用普通的内存数据库进行测试。可以通过 DataSource 访问数据库连接,该 DataSource 将连接管理推迟到 ConnectionPool。
如何在单元测试中模拟 temporary/intermitent 数据库断开连接以验证正确的错误处理和从连接中断中恢复?
如@duffymo 所述,模拟是可行的方法。
如果您真的要进行单元测试,您已经会使用由模拟框架创建的模拟,因为单元测试需要隔离个体将 dependencies 替换为 test doubles 的单位。模拟框架是创建此类 测试替身 的最简单和最稳定的方法。
但我猜你是在用 UnitTesting Framework 执行 Integration Tests,称它们为 "unit tests"原因。
然而..
由于您的测试依赖于数据源的实际功能,因此 spy 将是一个不错的选择,如下所示:
class DatasourceUsageTest{
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void reportDatabaseOutage(){
// arrange
DataSource myDatasource = aquireDatasourceSomehow();
DataSource spyOfMyDatasource = Mockito.spy(myDatasource);
Mockito.doCallRealMethod() // first call
.doThrow(new SqlException("Report this message") // second call (and all following)
.when(spyOfMyDatasource).methodExpectedToFail();
SomeType testedUnit = createUnitAndInject(spyOfMyDatasource );
// act call #1
testedUnit.theMethodUsingDatasource();
Mockito.verify(spyOfMyDatasource).methodExpectedToFail();
// act call #2
exception.expect(TheExceptionTypeToBeThrown.class);
exception.expectMessage(EXCEPTION_MESSAGE_PREFIX + "Report this message");
testedUnit.theMethodUsingDatasource();
// Code below this will not be executed
}
}
这里的问题(与任何 集成测试 一样)是您的数据库可能有一个真正的问题,在这种情况下,此测试在调用 #1 时失败(因此原因错误).