面试题答案
一键面试测试策略和重点的不同
- 接口
- 测试策略:接口本身不能被实例化,测试时需通过实现该接口的类来间接测试接口方法。通常采用针对接口的不同实现类分别进行测试,以验证每个实现类对接口契约的遵循情况。
- 测试重点:验证实现类是否正确实现了接口中定义的所有方法,确保方法签名、返回值类型和行为符合接口定义。关注接口方法的功能性,例如输入不同参数时,方法是否返回预期结果。同时检查实现类在实现接口方法过程中,对异常情况的处理是否符合接口的隐含或明确规定。
- 抽象类
- 测试策略:由于抽象类不能被实例化,但可以包含具体方法和抽象方法。测试时需创建抽象类的具体子类来测试其具体方法。对于抽象方法,需检查子类是否正确重写。
- 测试重点:对于抽象类的具体方法,重点测试其功能逻辑是否正确。对于抽象方法,要验证子类重写后的行为是否符合抽象类设计的预期。同时关注抽象类中可能存在的受保护方法和字段,测试它们在子类继承后的访问和使用是否合理。还要测试抽象类中对继承和多态机制的支持,例如子类调用抽象类的具体方法时,是否能正确利用抽象类中的上下文和逻辑。
以Junit为例编写单元测试代码
- 接口的单元测试
假设存在一个接口
Calculator
:
public interface Calculator {
int add(int a, int b);
}
实现类 SimpleCalculator
:
public class SimpleCalculator implements Calculator {
@Override
public int add(int a, int b) {
return a + b;
}
}
Junit测试代码:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CalculatorTest {
@Test
public void testAdd() {
Calculator calculator = new SimpleCalculator();
int result = calculator.add(2, 3);
assertEquals(5, result);
}
}
- 抽象类的单元测试
假设存在一个抽象类
Shape
:
public abstract class Shape {
public double getArea() {
// 这里可以有通用逻辑,比如某些形状面积计算的公共部分
return 0;
}
public abstract double getPerimeter();
}
具体子类 Circle
:
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public double getPerimeter() {
return 2 * Math.PI * radius;
}
}
Junit测试代码:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class ShapeTest {
@Test
public void testCircleArea() {
Shape circle = new Circle(5);
assertEquals(25 * Math.PI, circle.getArea(), 0.0001);
}
@Test
public void testCirclePerimeter() {
Shape circle = new Circle(5);
assertEquals(10 * Math.PI, circle.getPerimeter(), 0.0001);
}
}