有 Java 编程相关的问题?

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

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

我有一段代码,希望用JavaUUID(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;
}

共 (4) 个答案

  1. # 1 楼答案

    编辑:在获得了更多的单元测试经验之后,我会选择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();
        }
    }
    

    在测试中注入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()
    }
    

    我以前的答案如下


    除了ThinkBonobo的响应之外,另一种方法是创建一个getter方法(可选地用@VisibleForTesting注释),例如String getUUID(),它可以在测试中定义的子类中重写

  2. # 2 楼答案

    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");
        ...
        }
    

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

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

    A a = doSomething();
    assertEquals("your-UUID", a.getX());
    
  3. # 3 楼答案

    当您需要模拟时,类/静态方法会成为一个真正的难题。我最后做的是使用一个瘦包装器类和一个实现静态方法的接口,这样可以避免使用模拟系统

    在代码中,实例化/注入并使用包装器类而不是静态方法。这样你就可以用模拟来代替它

  4. # 4 楼答案

    关于this existing question,似乎我能够成功模拟UUID的唯一方法是,如果我在@PrepareForTesting下添加了我想要测试的类:

    @PrepareForTesting({UUIDProcessor.class})
    @RunWith(PowerMockitoRunner.class)
    public class UUIDProcessorTest {
        // tests
    }