【问题标题】:How to mock UUID.randomUuid() and System.currentTimeMillis() without PowerMock?如何在没有 PowerMock 的情况下模拟 UUID.randomUuid() 和 System.currentTimeMillis()?
【发布时间】:2021-09-27 17:44:25
【问题描述】:

我正在改进我的代码覆盖率,并且我正在使用 Sonar 来计算它。 但是 Sonar 和 PowerMock 不是很兼容。我想知道是否有另一种方法可以在不使用 PowerMock 的情况下模拟 UUID.randomUUID() 和 System.currentTimeMillis() 方法?

【问题讨论】:

  • 模拟你不拥有的类是一种不好的模拟实践。模拟静态方法是另一种不好的模拟实践。使用 Powermock (或类似的)是一种气味。您可以更改代码以传递ClockSupplier<UUID> 的实例吗?这将使您的测试代码更简单,并且需要更少的巫术(在运行时重写类)。

标签: junit sonarqube powermock


【解决方案1】:

我知道 PowerMock 会带来困难,但我不知道 SonarQube 与它不兼容的任何原因。

无论如何,最新版本的 Mockito 可以模拟静态方法(虽然我还没有使用过):https://www.baeldung.com/mockito-mock-static-methods

【讨论】:

【解决方案2】:

正如@Augusto 正确指出的那样,应该引入依赖关系而不是依赖静态方法调用。那么你根本不需要powermock。

假设您的工具是 JUnit5、assertj 和 mockito。一个例子是这样的:

// -- production code --

import java.util.UUID;
import java.util.function.Supplier;

public class ProductionCode {
    private final Supplier<String> idSupplier;
    private final Supplier<Long> clock;

    // @VisibleForTesting
    ProductionCode(Supplier<String> idSupplier, Supplier<Long> clock) {
        this.idSupplier = idSupplier;
        this.clock = clock;
    }

    public ProductionCode() {
        this(() -> UUID.randomUUID().toString(), System::currentTimeMillis);
    }

    public String methodUnderTest() {
        return String.format("%s -- %d", idSupplier.get(), clock.get());
    }
}

// -- test code without mocking

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

public class Tests {
    @Test
    void methodUnderTest_shouldSeparateByDoubleDashRandomIdAndCurrentTime() {
        ProductionCode objectUnderTest = new ProductionCode(() -> "id", () -> 1234L);

        String s = objectUnderTest.methodUnderTest();

        assertThat(s).isEqualTo("id -- 1234");
    }
}

// -- test code (mockito) --

import static org.assertj.core.api.Assertions.assertThat;

import java.util.function.Supplier;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

public class Tests {
    private final Supplier<String> idSupplier = Mockito.mock(Supplier.class);
    private final Supplier<Long> clock = Mockito.mock(Supplier.class);
    private final ProductionCode objectUnderTest = new ProductionCode(idSupplier, clock);

    @Test
    void methodUnderTest_shouldSeparateRandomIdAndCurrentTimeByDoubleDash() {
        Mockito.when(idSupplier.get()).thenReturn("id");
        Mockito.when(clock.get()).thenReturn(1234L);

        String s = objectUnderTest.methodUnderTest();

        assertThat(s).isEqualTo("id -- 1234");
    }
}

【讨论】:

    猜你喜欢
    • 2017-12-11
    • 2011-08-06
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 2021-03-31
    • 2022-11-17
    • 2023-01-08
    • 2022-11-10
    相关资源
    最近更新 更多