Java Mockito中的嵌套方法mocking
我有以下Java类:Java Mockito中的嵌套方法mocking,java,junit,mocking,mockito,Java,Junit,Mocking,Mockito,我有以下Java类: public class A { @Autowired private B b; public int aFn() { int something = b.bFn(); } } public class B { @Autowired private C c; public int bFn() { int something = c.cFn(); } } publi
public class A
{
@Autowired
private B b;
public int aFn()
{
int something = b.bFn();
}
}
public class B
{
@Autowired
private C c;
public int bFn()
{
int something = c.cFn();
}
}
public class C
{
public int cFn()
{
return 231;
}
}
下面使用Mockito测试上述代码:
public class test
{
@Autowired
private A a;
private C c;
@Test
public void testA()
{
c = mock(C.class);
when(c.cFn(),anyInt()).thenReturn(something);
assertEquals(0, a.aFn());
}
}
当我调试testA时,我发现执行的是真正的c.Cfn(),而不是模拟的。
我在这里做的有什么不对吗?
请帮忙 首先,您应该始终模拟对象的直接依赖关系,而不是其可传递依赖关系。所以您应该模拟B而不是C来测试A。然后您可以通过模拟C来为B编写单元测试 第二:在单元测试的任何地方都没有注入模拟。你应该做的是:
public class Test {
// not autowired here
private A a;
private B mockB;
@Test
public void testA() {
mockB = mock(B.class);
when(b.bFn(), anyInt()).thenReturn(something);
// the missing part: injecting the mock into the tested object
a = new A(mockB);
// or a = new A();
// a.setB(mockB);
assertEquals(0, a.aFn());
}
}
当您使用mock(B.class)时,您会得到一个B的mock实例。这并不意味着B的所有其他实例都将执行mock所做的操作
模拟C来测试A是一种不好的做法:单元测试应该测试一个类而不是其他类。但是如果你真的想这样做,那么创建一个模拟C,创建一个B并在其中注入模拟C,然后创建一个a并在其中注入B
A --> B --> mockC
忘记要模拟的是直接模拟还是嵌套模拟。 从斯普林的哲学观点来思考 实际上,您想要做的是模拟一个bean 在您的例子中,必须使用@MockBean注释来模拟类c的bean
@RunWith(SpringRunner.class)
public class Test {
...
@MockBean private C c;
...
}
有关详细信息,请参阅。我要存根c.cFn,而不是b.bFn。那该怎么办?那是个坏习惯。单元测试应该测试一个类,而不测试其他类。但是如果你想要的话,那么创建一个模拟C,创建一个B,并在其中注入模拟C,然后创建一个a,并在其中注入B<代码>A-->B-->模拟C。谢谢。请根据该修改您的答案。JB,您只讨论了单元测试,但问题从未指定测试是单元测试,或者SUT是单个类。在许多情况下,如果SUT由一个以上的类组成(在本例中为a类和B类),则进行测试是有意义的。我经常自己编写此类测试,尤其是如果B类包含有助于履行a类合同的大部分逻辑。我不同意您将其描述为“不良做法”,只要清楚哪些类包含在哪些测试中。你回答的最后一段救了你,赢得了我的选票!