如何模拟私有dao变量?

时间:2012-11-30 12:45:48

标签: java junit mockito powermock

我在测试方法时想要模拟dao.create()调用。 但我错过了一些东西,因为我还在接受NPE。这有什么不对?

class MyService {
    @Inject
    private Dao dao;

    public void myMethod() {
        //..
        dao.create(object);
        //
    }
}

如何模拟dao.create()调用?

@RunWith(PowerMockRunner.class)
@PrepareForTest(DAO.class)
public void MyServiceTest {

    @Test
    public void testMyMethod() {
        PowerMockito.mock(DAO.class);

        MyService service = new MyService();
        service.myMethod(); //NPE for dao.create()
    }
}

5 个答案:

答案 0 :(得分:5)

你没有注射DAO。使用mockito,您可以更改测试类以使用@InjectMocks并使用mockito runner。

@RunWith(MockitoJUnitRunner.class)
public void MyServiceTest {
    @Mock
    private Dao dao;
    @InjectMocks
    private MyService myService;
    ...
}

您可以在Inject Mocks API

了解有关InjectMocks的更多信息

更简单的方法是通过构造函数将注入更改为注入。例如,您可以将MyService更改为

class MyService {
    ...
    private final Dao dao;

    @Inject
    public MyService(Dao dao) {
        this.dao = dao;
    } 
    ...
}

然后你的测试你可以简单地在设置中传递模拟的DAO。

...
@Mock
private Dao dao;

@Before
public void setUp() {
    this.dao = mock(Dao.class);
    this.service = new MyService(dao);
}
...

现在您可以使用verify来检查是否调用create,例如:

...
   verify(dao).create(argThat(isExpectedObjectBeingCreated(object)));
}

private Matcher<?> isExpectedObjectBeingCreated(Object object) { ... }

使用构造函数注入将使您的依赖关系更清晰,并且在创建测试时会有所帮助:)

答案 1 :(得分:1)

您仍然需要使用模拟设置dao字段。 你可以使用反射。

答案 2 :(得分:1)

您需要在服务类中注入/设置模拟对象DAO。

如果是一个基于弹簧的项目,你可以看看@Spring Junit Testrunner

答案 3 :(得分:0)

如果使用new MyService(),Dao永远不会注入。要注入Dao,您需要通过ApplicationContext(Spring)或Injector(Guice)加载MyService。就像你在正常的应用程序中一样。

答案 4 :(得分:0)

正如其他人已经说过的那样,您需要以某种方式在dao课程中设置MyService字段。我不确定允许测试中的复合运行器同时使用Powermock和DI框架运行器(假设需要Powermock)的机制,但只要您已经在使用PowerMock(由于给定示例中不明确的原因) ,您可以利用Whitebox类来手动设置dao。

public void testMyMethod() {
    Dao dao = mock(Dao.class)
    doNothing().when(dao).create(anyObject())); //assuming no return val for dao.create()

    MyService service = new MyService();
    Whitebox.setInternalState(service, "dao", dao);

    service.myMethod(); 
}