为什么我们不能使用Mockito为Parameterized Constructor创建间谍

时间:2017-08-04 20:20:11

标签: java mockito junit4

我的代码中只有参数化构造函数,我需要通过它注入。

我想间谍参数化构造函数将模拟对象注入我的junit的依赖项。

public RegDao(){
 //original object instantiation here
Notification ....
EntryService .....
}

public RegDao(Notification notification , EntryService entry) {
 // initialize here
}

we have something like below : 
RegDao dao = Mockito.spy(RegDao.class);

但是我们有什么东西可以在构造函数中注入模拟对象并窥探它吗?

2 个答案:

答案 0 :(得分:10)

你可以通过在junit中使用参数化构造函数实例化主类,然后从中创建一个间谍来实现。

假设您的主要班级是 2018-05-16 08:17:52.334189 DBG:FsLonSource.cpp L01079SQ00011ET 5.334189 CFsLonSource::SubmitCommand(AddressType:Local NI, Mode:0, Selector:0) 2018-05-16 08:17:52.334449 DBG:NodetalkLONInterface.c L01862SQ00012ET 5.334449 AdapterSetAddress(DomainId:, SubnetId:1, NodeId:1) 2018-05-16 08:17:52.334807 DBG:NodetalkLONInterface.c L01522SQ00013ET 5.334807 AdapterSetAddressInternal(DomainId:, SubnetId:1, NodeId:1) 2018-05-16 08:17:52.335413 DBG:NodetalkLONInterface.c L01021SQ00014ET 5.335413 NodeSetAddress(ServiceType: ACKD): ok 2018-05-16 08:17:52.335603 DBG:NodetalkLONInterface.c L01055SQ00015ET 5.335603 NodeSetModeState() 2018-05-16 08:17:52.335783 DBG:NodetalkLONInterface.c L01064SQ00016ET 5.335783 ServiceType: UNACKD 2018-05-16 08:17:52.335966 DBG:NodetalkLONInterface.c L01065SQ00017ET 5.335966 NewMode: ? 2018-05-16 08:17:52.336124 DBG:NodetalkLONInterface.c L01071SQ00018ET 5.336124 NewState: Configured, Online 2018-05-16 08:17:52.339081 DBG:FsLonDispatch.cpp L00342SQ00019ET 5.339081 CFsLonDispatch::ExecRequest(): S_OK 2018-05-16 08:17:52.433098 DBG:FsLonDispatch.cpp L00181SQ00020ET 5.433098 CFsLonDispatch::ExecRequest(request:"<UpdateRest xmln", lTimeout:0, destination:"", correlationId:"") 2018-05-16 08:17:52.436138 DBG:FsLonDispatch.cpp L00250SQ00021ET 5.436138 strCCommand: UpdateRest 2018-05-16 08:17:52.436431 DBG:FsLonDispatch.cpp L00342SQ00022ET 5.436431 CFsLonDispatch::ExecRequest(): S_OK 2018-05-16 08:17:52.437184 DBG:FsLonDispatch.cpp L00181SQ00023ET 5.437184 CFsLonDispatch::ExecRequest(request:"<UpdateRest xmln", lTimeout:0, destination:"", correlationId:"") 2018-05-16 08:17:52.439981 DBG:FsLonDispatch.cpp L00250SQ00024ET 5.439981 strCCommand: UpdateRest 2018-05-16 08:17:52.440331 DBG:FsLonDispatch.cpp L00342SQ00025ET 5.440331 CFsLonDispatch::ExecRequest(): S_OK 2018-05-16 08:17:52.440705 DBG:FsLonDispatch.cpp L00181SQ00026ET 5.440705 CFsLonDispatch::ExecRequest(request:"<UpdateRest xmln", lTimeout:0, destination:"", correlationId:"") 2018-05-16 08:17:52.443586 DBG:FsLonDispatch.cpp L00250SQ00027ET 5.443586 strCCommand: UpdateRest 2018-05-16 08:17:52.443792 DBG:FsLonDispatch.cpp L00342SQ00028ET 5.443792 CFsLonDispatch::ExecRequest(): S_OK 2018-05-16 08:17:52.951870 DBG:NodetalkLONInterface.c L01108SQ00029ET 5.951870 ServiceType: REQUEST 2018-05-16 08:17:52.955944 DBG:NodetalkLONInterface.c L01152SQ00030ET 5.955944 NodeSetModeState(): ok 2018-05-16 08:17:52.956289 DBG:NodetalkLONInterface.c L01555SQ00031ET 5.956289 AdapterSetAddressInternal(): ok 2018-05-16 08:17:52.956655 DBG:NodetalkLONInterface.c L01597SQ00032ET 5.956655 AdapterSetRcvTimer(ServiceType: REQUEST, AddressType: LOCAL) 2018-05-16 08:17:52.966897 DBG:NodetalkLONInterface.c L01625SQ00033ET 5.966897 AdapterSetRcvTimer(): ok 2018-05-16 08:17:52.967216 DBG:NodetalkLONInterface.c L01878SQ00034ET 5.967216 AdapterSetAddress(): ok 2018-05-16 08:17:52.967531 DBG:FsLonSource.cpp L01174SQ00035ET 5.967531 CFsLonSource::SubmitCommand(): ok AB是其依赖项的位置

C

然后你可以使用你的参数化类来编写junit,如下所示

public class A {

    private B b;

    private C c;

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

    void method() {
        System.out.println("A's method called");
        b.method();
        c.method();
        System.out.println(method2());

    }

    protected int method2() {
        return 10;
    }
}

测试类的输出

@RunWith(MockitoJUnitRunner.class)
public class ATest {

    A a;

    @Mock
    B b;

    @Mock
    C c;

    @Test
    public void test() {
        a=new A(b, c);
        A spyA=Mockito.spy(a);

        doReturn(20).when(spyA).method2();

        spyA.method();
    }
}
  1. 此处A's method called 20 B是使用参数化构造函数在类C中注入的模拟对象。
  2. 然后我们创建了一个名为A的{​​{1}} spy
  3. 我们通过修改类A中受保护方法spyA的返回值来检查spy是否确实有效,如果method2不是A的实际spyA

答案 1 :(得分:0)

听起来您可能错过了依赖注入解决方案。 Mockito非常适合与你的DI一起注射嘲笑。例如,您可以使用CDI,为NotificationEntryService成员注释@Inject,在测试中为两者声明@Mock,然后让Mockito将这些内容注入您的RegDao进行测试。

这是我认为你试图运行的测试的工作模型:

import static org.junit.Assert.assertEquals;

import javax.inject.Inject;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MockitoSpyInjection {
    static class Notification { }
    static class EntryService { }
    static class RegDao {
        @Inject
        Notification foo;

        @Inject
        EntryService  bar;

        public RegDao() {
        }

        public RegDao(Notification foo, EntryService bar) {
            this.foo = foo;
            this.bar = bar;
        }

        public Notification getFoo() {
            return foo;
        }

        public EntryService getBar() {
            return bar;
        }

    }


    @Mock
    Notification foo;

    @Mock
    EntryService bar;

    @Spy
    @InjectMocks
    RegDao dao;

    @Test
    public void test() {
        assertEquals(foo, dao.getFoo());
        assertEquals(bar, dao.getBar());
    }
}