如何模拟私有dao变量?

我有一个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() } } 

你没有注射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) { ... } 

使用构造函数注入将使您的依赖关系更清晰,其他开发人员将在创建测试时有所帮助:)

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

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

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

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

正如其他人已经说过的那样,您需要以某种方式在MyService类中设置dao字段。 我不确定允许测试中的复合运行器同时使用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(); }