如何对使用Java UUID的代码进行单元测试?

Har*_*ish 6 java uuid unit-testing

我有一段代码,希望用Java UUID(UUID.randomUUID())填充响应对象的一个​​属性.

如何从外部对此代码进行单元测试以检查此行为?我不知道将在其中生成的UUID.

需要测试的示例代码:

// To test whether x attribute was set using an UUID
// instead of hardcode value in the response
class A {
  String x;
  String y;
}

// Method to test
public A doSomething() {
  // Does something
  A a = new A();
  a.setX( UUID.randomUUID());
  return a;
}
Run Code Online (Sandbox Code Playgroud)

RZe*_*Zet 9

Powermock和静态模拟是前进的方向.你需要这样的东西:

    ...
    import static org.junit.Assert.assertEquals;
    import static org.powermock.api.mockito.PowerMockito.mockStatic;
    ...

    @PrepareForTest({ UUID.class })
    @RunWith(PowerMockRunner.class)
    public class ATest
    {
    ...
      //at some point in your test case you need to create a static mock
      mockStatic(UUID.class);
      when(UUID.randomUUID()).thenReturn("your-UUID");
    ...
    }
Run Code Online (Sandbox Code Playgroud)

请注意,静态模拟可以在使用@Before注释的方法中实现,因此可以在需要UUID的所有测试用例中重复使用它,以避免代码重复.

初始化静态模拟后,可以在测试方法中的某个位置声明UUID的值,如下所示:

A a = doSomething();
assertEquals("your-UUID", a.getX());
Run Code Online (Sandbox Code Playgroud)

  • `@PrepareForTest({UUID.class})`没有意义,因为它是最终的系统类.因此它总是由引导类加载器加载.PowerMock无法修改它.但是PowerMock可以替换对UUID类的调用.必须将使用"UUID"的类添加到"@PrepareForTest". (4认同)

Era*_*nah 7

编辑:在单元测试方面获得了更多经验后,我会选择 ThinkBonobo 的答案。创建一个接口、一个假实现和一个具体实现,如下所示:

public interface UuidProvider {
    UUID uuid();

    class Fake implements UuidProvider {
        @Override
        public UUID uuid() {
            return UUID.fromString("0000-00-00-00-000000");
        }
    }
}

public class RandomUuidProvider implements UuidProvider {
    @Override
    public UUID uuid() {
        return UUID.randomUUID();
    }
}
Run Code Online (Sandbox Code Playgroud)

注入UuidProvider.Fake您的测试和RandomUuidProvider生产代码中。

或者在科特林中:

interface UuidProvider {
    fun uuid(): UUID

    class Fake : UuidProvider {
        override fun uuid() = UUID.fromString("0000-00-00-00-000000")
    }
}

class RandomUuidProvider : UuidProvider {
    override fun uuid() = UUID.randomUUID()
}
Run Code Online (Sandbox Code Playgroud)

我的旧答案如下。


除了 ThinkBonobo 的响应之外,还有另一种方法来创建 getter 方法(可以选择用 注释@VisibleForTesting),例如String getUUID()可以在您在测试中定义的子类中覆盖该方法。