Spock:如何让不在被测类中的静态方法返回某个值?

OEu*_*rix 2 groovy unit-testing spock

我正在使用 Spock 和 Groovy 来测试一个类:

public class Animal {
    public void findAnimal() {
        findAnimalInZoo();     
    }

    private void findAnimalInZoo() {
        if (!isGoodWeather) {
            throw Exception;
        }
    }

    private boolean isGoodWeather() {
        return "good".equals(Weather.getWeather());
    }
}
Run Code Online (Sandbox Code Playgroud)

Weather班级:

public class Weather {
    public static String getWeather() {
        return instance.getWeather();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,在方法的每个测试用例中findAnimal(),我想指定调用时返回的值Weather.getWeather()

def "when it is good weather then expect no exception"() {
    setup:
    // What should I do for Weather.getWeather()?    
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到呢?

Lui*_*ñiz 6

如果你的生产代码是Java,那么你不能使用Spock模拟来模拟静态方法。如果您的生产代码是 Groovy,您可以使用:

GroovyMock(Weather, global: true)
Weather.getWeather() >> "good"
Run Code Online (Sandbox Code Playgroud)

如果您坚持使用 Java,那么您需要使用 Powermock 或 JMockit 来实现此目的。

def "when it is good weather then expect no exception"() {
    setup:
    PowerMockito.mockStatic(Weather)
    when(Account.getWeather()).thenReturn("good")
}
Run Code Online (Sandbox Code Playgroud)

参考: https: //dzone.com/articles/mocking-static-methods-groovy

迂腐警告 我知道你并不总是能够控制或改进你正在测试的代码,所以接受这个建议并注意这一点。

当您需要花费如此多的精力来测试您的代码时,您的代码就会向您大喊,它的设计很糟糕。您的代码与 Weather 类紧密耦合。除非你通过重写类来使用虚拟机,否则不可能将其切换为其他东西。这不仅意味着您的测试代码无法做到这一点,而且您的生产代码也不必要地不灵活。