6

我有以下 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();
    }
}
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() 被执行,而不是被模拟的。我在这里做错了什么吗?请帮忙!

4

2 回答 2

10

首先,你应该总是模拟一个对象的直接依赖,而不是它的传递依赖。所以你应该模拟 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
于 2013-08-21T16:02:02.013 回答
0

忘记你想要模拟的是直接的还是嵌套的。从 Spring 的哲学角度来考虑它。

你本质上想要做的是模拟一个bean。

在您的情况下,您必须使用 @MockBean 注释为 Class c 模拟 bean。

@RunWith(SpringRunner.class)
public class Test {
...
@MockBean private C c;
...
}

详情请参考这篇文章

于 2019-08-31T04:17:38.417 回答