Java 在Mockito中使用泛型处理匿名类

Java 在Mockito中使用泛型处理匿名类,java,unit-testing,mockito,powermockito,Java,Unit Testing,Mockito,Powermockito,我正在尝试使用Powermockito为以下方法编写单元测试- public String getGenerator(String json) throws IOException { String jwt = ""; ObjectMapper mapper = new ObjectMapper(); // convert JSON string to Map Map<String, Object> map = mapper.readValue(js

我正在尝试使用Powermockito为以下方法编写单元测试-

public String getGenerator(String json) throws IOException {
    String jwt = "";
    ObjectMapper mapper = new ObjectMapper();

    // convert JSON string to Map
    Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {
    }); // Here passing TypeReference annonymously

    // Create a JWT
    JWTGenerator generator = new JWTGenerator();
    if (map != null && map.size() > 0) {
        jwt = generator.createJWT(map);
    }

    return jwt;
}
看起来存根不起作用了,因为这一行的值总是为空-

Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {
        }); // Here passing TypeReference annonymously

是因为TypeReference类的匿名实例化吗?

是的,是因为匿名内部类。具体来说,您告诉PowerMockito替换对new TypeReference的调用:

但您实际创建的是一个扩展TypeReference的匿名类,而不是TypeReference本身:

Map<String, Object> map = mapper.readValue(
    json, new TypeReference<Map<String, Object>>() {});
这对你来说会特别棘手。这里我通常的建议类似于TypeReference,因为它是一个无依赖性的令牌/值/数据对象,在反射方面起着重要作用,但它也和它在Guice和Guava中的表亲一样;你不能只是在测试中创建自己的真实类型引用,并将eq与课堂上的真实类型进行比较

您仍然不应该模拟TypeReference,但还需要调整针对它的断言方式:

如果Jackson允许,将匿名TypeReference子类提取到一个命名的等价类,然后使用isA检查其类型。 将TypeReference提取到一个可见常量,并检查其引用相等性。 使用捕获器,稍后使用反射检查TypeReference的泛型类型。 切换到Mockito.any,从技术上讲,它位于Matchers类上,或者在Mockito的较新版本中切换到ArgumentMatchers。无论如何,该值都不太可能改变,因此从实用角度讲,忽略检查可能比说服PowerMock更具可读性和健壮性。 理想情况下,尽可能使用真正的依赖项,只需检查功能是否正常工作,而不是检查您是否以实现的方式与正确的协作者交互。一个工作函数就是你想要的,对吧?
是的,这是因为匿名的内部类。具体来说,您告诉PowerMockito替换对new TypeReference的调用:

但您实际创建的是一个扩展TypeReference的匿名类,而不是TypeReference本身:

Map<String, Object> map = mapper.readValue(
    json, new TypeReference<Map<String, Object>>() {});
这对你来说会特别棘手。这里我通常的建议类似于TypeReference,因为它是一个无依赖性的令牌/值/数据对象,在反射方面起着重要作用,但它也和它在Guice和Guava中的表亲一样;你不能只是在测试中创建自己的真实类型引用,并将eq与课堂上的真实类型进行比较

您仍然不应该模拟TypeReference,但还需要调整针对它的断言方式:

如果Jackson允许,将匿名TypeReference子类提取到一个命名的等价类,然后使用isA检查其类型。 将TypeReference提取到一个可见常量,并检查其引用相等性。 使用捕获器,稍后使用反射检查TypeReference的泛型类型。 切换到Mockito.any,从技术上讲,它位于Matchers类上,或者在Mockito的较新版本中切换到ArgumentMatchers。无论如何,该值都不太可能改变,因此从实用角度讲,忽略检查可能比说服PowerMock更具可读性和健壮性。 理想情况下,尽可能使用真正的依赖项,只需检查功能是否正常工作,而不是检查您是否以实现的方式与正确的协作者交互。一个工作函数就是你想要的,对吧?
谢谢你的详细解释。我换了Mockito。杰夫·鲍曼,我也面临着同样的问题。你能解释更多或者提供一个例子吗?@Nimesh我可以回答一些具体的问题,但是我不知道重点领域或者你的限制,我不知道我还没有写过什么。至于例子,我列出了足够多的技巧和足够多的方法,我不确定预先为每种方法写一个具体的例子是否有意义。你能检查一下我在这里发布的问题吗:谢谢你的详细解释。我换了Mockito。杰夫·鲍曼,我也面临着同样的问题。你能解释更多或者提供一个例子吗?@Nimesh我可以回答一些具体的问题,但是我不知道重点领域或者你的限制,我不知道我还没有写过什么。举个例子,我列出了足够多的技巧和足够多的方法,我不确定预先为每种技巧写一个具体的例子是否有意义。你能检查一下我在这里发布的问题吗:
PowerMockito.whenNew(TypeReference.class).withNoArguments()
    .thenReturn(mockTypeReference);
Map<String, Object> map = mapper.readValue(
    json, new TypeReference<Map<String, Object>>() {});