Java 重构与测试
我试图以某种方式进行单元测试的场景示例: 方法获取三个参数:Java 重构与测试,java,unit-testing,junit,mockito,test-refactoring,Java,Unit Testing,Junit,Mockito,Test Refactoring,我试图以某种方式进行单元测试的场景示例: 方法获取三个参数:公司名称,飞机编号1,飞机编号2 public Double getDistanceBetweenPlanes(Sting company, String plane1, String plane2) { -Apply some validation logic to see that plane numbers and company realy exists -Use complex geLocation and setel
公司名称
,飞机编号1
,飞机编号2
public Double getDistanceBetweenPlanes(Sting company, String plane1, String plane2)
{
-Apply some validation logic to see that plane numbers and company realy exists
-Use complex geLocation and setelate data to get plane location
return plane1.geoLocation() - plane2.geoLocation() ;
}
现在,我想对这个进行单元测试
我没有真实的飞机号码,也没有与卫星的实时连接
尽管如此,我还是希望能够以某种方式模拟整个过程,以便能够测试这个API。
有关于如何重构它的建议吗?要创建任何新的公共方法来进行测试吗?您可以使用类似jmock或easy mock的mock 使用jmock,您可以编写如下内容:
@Test
public testMethod(){
Mockery context = new Mockery();
plane1 = context.mock(Plane.class);
plane2 = context.mock(Plane.class);
context.expectations(new Expectations(){{
oneOf(plane1).geoLocation(); will(returnValue(integerNumber1));
oneOf(plane2).geoLocation(); will(returnValue(integerNumber2));
}});
assertEquals(
instanceUnderTest.method(plane1,plane2),
integerNumber1-integerNumber2
)
context.assertIsSatisfied()
}
最后一个方法将确保调用根据期望设置的方法。如果没有引发异常,测试就会失败。通常在重构未经测试的代码时,我指的是我在练习TDD和BDD时会做什么 所以首先我要写一个简单的合同,一行=一个需求(现有代码)。 然后在编写测试代码时,我可能会注意到一些我不想测试的东西。在这种情况下,DI将帮助您删除对另一个类负有不同责任的代码。在进行对象设计时,重点关注具有不同关注点的对象之间的行为和交互非常重要。Mockito具有别名类BDDMockito,可以帮助您支持这种方法 在你的情况下,这里有一个你可以做的例子
公共类平面定位器{
私人公司供应商公司供应商;
私人飞机供应商公司供应商;
私有位置util LocationUtil;
//构造函数注入还是属性注入
public Double获取平面之间的距离(字符串companyId、字符串plane1Id、字符串plane2Id){
Company Company=companyProvider.get(公司);
PlanePlane1=planeProvider.get(plane1Id);
PlanePlane1=planeProvider.get(plane1Id);
返回locationUtil.distance(plane1.geoLocation(),plane2.geoLocation());
}
}
一个简单的JUnit测试可能如下所示(使用mockito 1.9.0的特性):
@RunWith(MockitoJUnitRunner.class)
公开课考试{
@模拟公司供应商模拟公司供应商;
@模拟平面提供者模拟平面提供者;
@模拟LocationUtil LocationUtil;
@InjectMocks卫星计划探测仪测试计划探测仪;
@测试公共空间应使用位置util获取平面和位置之间的距离{
//给定
给定(companyProvider.get(anyString()).willReturn(newcompany());
给定(planeProvider.get(anyString()))
.willReturn(Plane.builder().withLocation(新位置(“A”))
.willReturn(Plane.builder().withLocation(新位置(“B”));
//什么时候
测试的平面指示器。获取平面之间的距离(“AF”、“1251”、“721”);
//然后
验证(locationUtil).距离(isA(Location.class)、isA(Location.class));
}
//平面定位器的其他更具体测试
}
您将注入以下依赖项,每个依赖项都有自己的单元测试来描述类的行为,考虑到输入和协作者:
公共类DefaultCompanyProvider实现CompanyProvider{
上市公司get(字符串companyId){
companyIdValidator.validate(companyId);
//检索/创建公司
返回公司;
}
}
公共类SatellitePlaneProvider实现PlaneProvider{
公共平面get(平面平面ID){
planeIdValidator.validate(planeId);
//使用昂贵的卫星数据检索/创建飞机(例如使用卫星服务)
返回平面;
}
}
使用这种方法,您可以以更低的耦合重构代码。更好地分离关注点将允许更好地理解代码库、更好的可维护性和更容易的演化
我还想让您在这篇博文中进一步阅读著名的Bob Martin叔叔在TDD中的转换优先级前提谢谢,但问题是主API方法的输入不是一个平面对象,而是一个带平面ID的字符串,基于带平面ID和公司ID的查询,在调用的方法的作用域内创建了一个平面对象。这正是我要找的。我承认我有点不舒服,因为它似乎为一些功能分配了代码,但这显然是值得学习的东西。