我正在为下面的代码编写单元测试
public class Class1 {
protected void execute(String a, String b) {
try{
process(a,b);
}
catch(Exception E){
Class2.write(e,Class1.class.getSimpleName())
}
}
private void process(String a, String b) {
validate(a,b);
// Doing some processing on a and b values
}
private void validate (String a, String b) {
if(a==null || a.isEmpty() || b==null || b.isEmpty())
throw new IllegalArgumentException("Input value cannot be null or empty");
}
}
对于上面的代码,我试图编写一个涵盖异常用例的UT。以下是我的UT代码,
@Test
public void test1(){
try {
PowerMockito.mockStatic(Class2.class);
PowerMockito.when(Class2.class, "write", Mockito.anyObject(), Mockito.anyString())
.thenCallRealMethod();
Class1 class1 = new Class1();
Class2.write(new IllegalArgumentException("Input value cannot be null or empty"),Class1.class.getSimpleClassName());
PowerMockito.verifyStatic(Class2.class, VerificationModeFactory.times(1));
class1.execute(Mockito.anyString(),Mockito.anyString());
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
执行上面的测试时,我得到下面的异常
Argument(s) are different! Wanted:
Class2.write{
java.lang.IllegalArgumentException:Input value cannot be null or empty,
Class1
}
Actual invocation has different arguments:
Class2.write{
java.lang.IllegalArgumentException:Input value cannot be null or empty,
Class1
}
有人可以帮助我解决此问题吗? 非常感谢您的帮助和时间
预先感谢
答案 0 :(得分:0)
IllegalArgumentException
不会将字符串消息用于相等性。测试字符串消息或类类型会更安全。我更希望测试检测类型而不是消息,因为字符串消息不应用于控制流,这是实现细节。
System.out.println(Objects.equals(
new IllegalArgumentException(),
new IllegalArgumentException()));
// false
System.out.println(Objects.equals(
new IllegalArgumentException().getClass(),
new IllegalArgumentException().getClass()));
// true
所以要模拟这个,我将使用匹配器:
any(IllegalArgumentException.class), eq(Class1.class.getSimpleName())
我将以反对该代码的结构为结尾,因为它不是围绕依赖注入构建的。您可以调用实例方法,而不是调用静态方法Class2::write
。
例如,创建接口:
public interface Writer {
void write(Exception e, String source);
}
您现在可以重构该类,以提供两个ctor,一个可以接受任何编写器,并且默认为Class2
。
public class Class1 {
private final Writer writer;
public Class1() {
this(Class2::write);
}
public Class1(Writer writer) {
this.writer = writer;
}
protected void execute(String a, String b) {
try {
process(a,b);
}
catch (Exception E) {
writer.write(e, Class1.class.getSimpleName());
}
}
...
}
使用此策略,您现在可以简单地创建Writer
的实例模拟。这样避免了必须模拟为更改应用程序字节码的静态方法,并且还可以使您的类更加灵活,因为它现在可以支持许多不同的writer实现。修改应用程序字节码的任何操作都应非常谨慎地使用,例如替换静态方法调用,并不能真正验证代码的运行时执行。
我认为,大多数PowerMockito / PowerMock仅有助于验证并非出于可测试性/灵活性而构建的代码。您无需使用Mockito / EasyMock工具集以外的任何东西来构建结构良好的代码。有一些例外,但是应该非常谨慎地使用工具集。