Java 验证是否创建了临时对象

Java 验证是否创建了临时对象,java,mocking,mockito,Java,Mocking,Mockito,我在java环境中,使用Mockito(但我不受其约束)满足基本的模拟需求 我有这样的代码 public class AuditInfoSerializer { [..] public Map<String, Object> doStuff(Object a) { doOtherStuff("hello", new TempClass(someField, <someParams>)); doOtherStuff("wo

我在java环境中,使用Mockito(但我不受其约束)满足基本的模拟需求

我有这样的代码

public class AuditInfoSerializer {

    [..]

    public Map<String, Object> doStuff(Object a) {
        doOtherStuff("hello", new TempClass(someField, <someParams>));
        doOtherStuff("world", new TempClass(someField, <otherParams>));
        return getResult();
    }
}
公共类序列化程序{
[..]
公共地图doStuff(对象a){
doOtherStuff(“你好”,新TempClass(someField,));
doOtherStuff(“世界”,新TempClass(someField,);
返回getResult();
}
}
在一个测试中,我想验证在调用
doStuff
方法时是否有两个使用正确参数集创建的
TempClass
实例


这可能吗?

您不想验证测试对象上的临时数据。您希望模拟依赖项并断言测试行为下的对象:即,通过此输入,您将获得此输出。
模拟验证是模拟方法的一种折衷,模拟方法只会产生副作用,而不返回任何结果。
所以,只有在你没有选择的时候才使用它。
在单元测试中,您需要断言测试方法返回的内容,即
getResult()


使用
Assert.assertEquals(…)
而不是使用
Mockito.verify(…)
执行此操作您不想验证测试对象上的临时数据。您希望模拟依赖项并断言测试行为下的对象:即,通过此输入,您将获得此输出。
模拟验证是模拟方法的一种折衷,模拟方法只会产生副作用,而不返回任何结果。
所以,只有在你没有选择的时候才使用它。
在单元测试中,您需要断言测试方法返回的内容,即
getResult()


使用
Assert.assertEquals(…)
而不是使用
Mockito.verify(…)
这样做在很大程度上我同意@davidxxx关于模拟验证权衡的观点。如果您有一个设置,允许您对结果做出断言,比如作为结果创建的地图,那么就去做吧

从API的角度来看,
doStuff
是一种简单直接的方法:向它扔东西,然后拿回东西。您感兴趣的信息将包含在地图中(这将是您的断言)

doStuff
返回一些东西之前,引擎盖下有很多事情要做。很多人在测试东西时倾向于打破封装。他们一直在寻找揭开幕后真相的方法。我相信这是很自然的。当然,这也是一种反模式。无论您(mis)使用什么工具打破自然边界(模拟框架、自定义反射、“代码库中的后门”等),这都无关紧要。它总是错的。正如@Michael已经指出的,调用
doOtherStuff
实际上是一个实现细节。从调用
doStuff
的客户机代码的角度来看。它对如何创建地图感兴趣吗?我对此表示怀疑。这也应该是您的测试视角

关于在测试中使用验证的最后一件事。我想缓和一下权衡声明。我真的不喜欢这里的概括。与真实断言相比,验证并不总是不那么吸引人的选择:

// Valid test without any verifaction
@Test
void method_foo_returns_gibberish (@Mock SomeInput someInput) {

    // Maybe this is just to prevent an NPE ...
    when(someInput.readStuff()).thenReturn("bla");

    assertEquals("gibberish", Foo.foo(someInput));

}


// Test made possible by verification
@Test
void method_foo_is_readonly (@Mock SomeInput someInput) {

    Foo.foo(someInput);
    verify(someInput.readStuff());
    verifyNoMoreInteractions(mockedList);

}
这是我能想到的最明显的例子。有一小部分BDD天才努力围绕验证驱动的测试构建他们的整个体系结构

当谈到测试时,大多数情况下,没有黑与白。使用模拟和验证意味着编写不同的测试


和往常一样,这是关于选择正确的工具。

在大多数情况下,我同意@davidxxx关于模拟验证权衡的观点。如果您有一个设置,允许您对结果做出断言,比如作为结果创建的地图,那么就去做吧

从API的角度来看,
doStuff
是一种简单直接的方法:向它扔东西,然后拿回东西。您感兴趣的信息将包含在地图中(这将是您的断言)

doStuff
返回一些东西之前,引擎盖下有很多事情要做。很多人在测试东西时倾向于打破封装。他们一直在寻找揭开幕后真相的方法。我相信这是很自然的。当然,这也是一种反模式。无论您(mis)使用什么工具打破自然边界(模拟框架、自定义反射、“代码库中的后门”等),这都无关紧要。它总是错的。正如@Michael已经指出的,调用
doOtherStuff
实际上是一个实现细节。从调用
doStuff
的客户机代码的角度来看。它对如何创建地图感兴趣吗?我对此表示怀疑。这也应该是您的测试视角

关于在测试中使用验证的最后一件事。我想缓和一下权衡声明。我真的不喜欢这里的概括。与真实断言相比,验证并不总是不那么吸引人的选择:

// Valid test without any verifaction
@Test
void method_foo_returns_gibberish (@Mock SomeInput someInput) {

    // Maybe this is just to prevent an NPE ...
    when(someInput.readStuff()).thenReturn("bla");

    assertEquals("gibberish", Foo.foo(someInput));

}


// Test made possible by verification
@Test
void method_foo_is_readonly (@Mock SomeInput someInput) {

    Foo.foo(someInput);
    verify(someInput.readStuff());
    verifyNoMoreInteractions(mockedList);

}
这是我能想到的最明显的例子。有一小部分BDD天才努力围绕验证驱动的测试构建他们的整个体系结构

当谈到测试时,大多数情况下,没有黑与白。使用模拟和验证意味着编写不同的测试


一如既往,关键在于选择正确的工具。

为什么您会关心是否创建了两个
TempClass
实例?这是一个实现细节。您需要关心的是返回的
映射
。至于它是否可能,则完全取决于
doOtherStuff
的实现,您尚未提供。在当前状态下,不。测试行为,而不是实现。例如,假设将
TempClass
替换为
ShinyAwesomeThingy
。只要
getResult()
继续返回