有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java测试在整个软件中使用适当的参数调用该方法

最近我遇到了一个问题,我服务中的一个方法被错误的参数调用。这导致了某种中断,所以我正在考虑如何在将来防止这种情况

假设我有以下方法:

public boolean doSomething(String param1, String param2);

我想验证每次调用此方法时(无论在我的服务中位于何处),param1值是特定的(例如,只有String1String2String3将是该方法的有效参数值

是否有任何技术/库/工具可以验证这一点,例如在单元测试中

更新:正如公认的答案所示,这是不应该通过单元测试来涵盖的,因为单元测试是用于行为测试的。防止将来错误调用的方法是使用Preconditions或只是简单的参数检查


共 (2) 个答案

  1. # 1 楼答案

    如果可能,您应该利用编译时检查,而不是将测试推迟到运行时。如果只有三个合法值,那么param1可能应该是enum而不是String

    单元测试用于验证方法是否以某种方式运行。他们把这种方法当作一个黑匣子,从外面捅出来。如果你关心如何被称为,它们就帮不了你。在这个方法中,你需要验证外部世界是否表现良好。实现这一点的方法是在方法的开头使用运行时先决条件检查

    public boolean doSomething(String param1, String param2) {
        if (!Objects.equals(param1, "String1") &&
            !Objects.equals(param1, "String2") &&
            !Objects.equals(param1, "String3"))
        {
            throw IllegalArgumentException("param1 must be String1, 2, or 3");
        }
    
        ...
    }
    

    番石榴酱可能会有帮助

    public boolean doSomething(String param1, String param2) {
        Preconditions.checkArgument(
            Objects.equals(param1, "String1") ||
            Objects.equals(param1, "String2") ||
            Objects.equals(param1, "String3"),
            "param1 must be String1, 2, or 3"
        );
    
        ...
    }
    
  2. # 2 楼答案

    创建一个单元测试,确保该方法在运行时只接受一些值作为param1参数

    用两种场景编写测试代码:有效和无效案例

    例如在JUnit 5中:

    @Test
    public void doSomething(){ 
       Assert.AssertTrue(new Foo().doSomething("String1", "anyValue");
       Assert.AssertTrue(new Foo().doSomething("String2", "anyValue");
       Assert.AssertTrue(new Foo().doSomething("String3", "anyValue");
    }
    
    @Test
    public void doSomething_with_illegal_argument(){ 
        Assert.assertThrows(IllegalArgumentException.class, () -> new Foo().doSomething("invalidValue", "anyValue"));
    }
    

    测试应该会失败,因为你实际上并不能保证这一点。 因此,改进您的实际实现,使测试通过

    例如:

    public boolean doSomething(String param1, String param2) {
        if (!"String1".equals(param1) &&
            !"String2".equals(param1) &&
            !"String3".equals(param1) {
            throw new IllegalArgumentException("param1 should be ...");
        }
       ... // processing
    }
    

    我想补充一点,如果失败的案例是任何String,那么一个测试单元不能覆盖所有失败的案例,而是3个特定的String:它创造了数百万种可能性

    在您的例子中,我认为使代码更健壮的最佳方法是使用有界类型作为枚举。因此,可以定义一个包含3个值的枚举,并提供一个枚举构造函数,其中String实际上是作为参数传递的

    它可能看起来像:

    public boolean doSomething(MyEnum param1Enum, String param2){
       ...
       String param1 = param1Enum.getString();
    }