嘲笑类方法在Java中不起作用

发布于 2025-02-12 22:08:48 字数 883 浏览 2 评论 0 原文

附加了代码及其测试下面:

public class A {
    private B b;

    public A(C c) {
        b = new B(c);
    }

    public ResponseOutput method1(RequestInput request) {
        ResponseOutput responseOutput = b.method2(param1, param2);
        //Do something based on responseOutput. e.g. throwException if some condition meet
        return responseOutput;
    }
}


public class ATest {

    @Mock
    private C c;
    @Mock
    private B b;
    @InjectMocks
    private A a;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void method1_test1() {
        ResponseOutput responseOutput = something;
        Mockito.when(b.method2(Mockito.any(), Mockito.any())).thenReturn(responseOutput);
        a.method1(param1, param2);
    }
}

B.Method2没有被模拟。呼叫将用于内部功能。嘲笑B类所需的其他注释还需要其他注释。

Attached the code and it's test below :

public class A {
    private B b;

    public A(C c) {
        b = new B(c);
    }

    public ResponseOutput method1(RequestInput request) {
        ResponseOutput responseOutput = b.method2(param1, param2);
        //Do something based on responseOutput. e.g. throwException if some condition meet
        return responseOutput;
    }
}


public class ATest {

    @Mock
    private C c;
    @Mock
    private B b;
    @InjectMocks
    private A a;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void method1_test1() {
        ResponseOutput responseOutput = something;
        Mockito.when(b.method2(Mockito.any(), Mockito.any())).thenReturn(responseOutput);
        a.method1(param1, param2);
    }
}

b.method2 is not getting mocked. Call is going to it's internal functions. Is there any other annotation needed for mocking class B.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜清冷一曲。 2025-02-19 22:08:48

首先,@InjectMocks将创建模拟对象(每次运行@Test方法时创建一个新对象)

但是,您没有使用该创建的实例 - 而是直接在@before方法中创建一个新实例。 @InjectMocks对创建的实例没有影响。

因此,您需要决定,您是否要使用创建的@InjectMocks,还是要使用自己的实例(在这种情况下,您必须设置B自己 - 也许使用PowerMock模拟新呼叫,或者使用使用Mockito 嘲笑测试类内的新实例创建类)。

此外,@InjectMocks仍将无法为您设置B @InjectMocks在@mock声明之后。

First, @InjectMocks will create the mock object (creating a new object every time an @Test method is run)

However, you are not using that created instance - instead you are creating a new instance directly in your @Before method. @InjectMocks has no effect on that created instance.

So you need to decide, do you want to use the @InjectMocks created instance of A, or do you you want to use your own (in which case, you must set b yourself - maybe using PowerMock to mock the new call, or alternatively use ideas from Mocking new instance creation inside testing class using mockito ).

In addition, @InjectMocks will still not set b for you, because Java initialises objects in order of declaration, which results in @InjectMocks only being able to inject @Mock variables declared before it - so you would have to switch the ordering around to have @InjectMocks AFTER the @Mock declarations.

陪我终i 2025-02-19 22:08:48

@InjectMock 将尝试使用最大的构造函数来创建和注入模拟的依赖关系(请参阅有关详细信息它的行为)在您的情况下是:

 A a = new A(c);

现在您在此构造函数内部手动创建一个B实例,该构造函数在A内部导致B是真实的实例,而不是模拟的实例。因此,您对模拟B的固执没有任何效果,因为A没有调用它。

实际上,A仅需要直接与B互动,因此您无需模拟C。第一个重构A可以直接使用B直接创建:

public class A {
    private B b;

    public A(B b) {
        this.b = b;
    }
} 

然后将测试更新为:

public class ATest {
    @Mock
    private B b;

    @InjectMocks
    private A a;


    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void method1_test1() {
 
    }
 }

请注意,您必须从A中删除constructor public a(c c) 。 > @InjectMocks 只会随机选择 public a(c c) public a(b b)创建一个,因为两者都是最大的构造函数。

如果您不想删除constructor public a(c c),请勿使用 @injectMocks 创建一个,但只需自己创建它:

public class ATest {
    @Mock
    private B b;


    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void method1_test1() {
        A a = new A(b);
        //do your test....
    }
 }

@InjectMock will try to use the biggest constructor to create and inject the mocked dependencies into A .(Refer this for detail of its behaviour) which in your case is :

 A a = new A(c);

Now you manually create a B instance inside this constructor which causes B inside A is a real instance but not a mocked one. So what you stub on the mocked B does not have any effect because A is not calling it.

Actually , A only needs to directly interact with B and so you do not need to mock C . First refactor A such that it can be directly created using B only :

public class A {
    private B b;

    public A(B b) {
        this.b = b;
    }
} 

And then update the test to :

public class ATest {
    @Mock
    private B b;

    @InjectMocks
    private A a;


    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void method1_test1() {
 
    }
 }

Please note that you have to remove the constructor public A(C c) from A. Otherwise , @InjectMocks will just randomly choose public A(C c) or public A(B b) to create A because both are the biggest constructors.

If you do not want to remove constructor public A(C c) , don't use @InjectMocks to create A but simply create it by yourself :

public class ATest {
    @Mock
    private B b;


    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void method1_test1() {
        A a = new A(b);
        //do your test....
    }
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文