如何模拟私有 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 运行器。

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

您可以在Inject Mocks API上阅读有关InjectMocks的更多信息

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

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) { ... }

使用 Injection by 构造函数将使其他开发人员更清楚地了解您的依赖项,并且在创建测试时会有所帮助:)

你仍然需要用你的模拟来设置dao字段。你可以对此使用反射。

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

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

如果你使用new MyService() Dao永远不会被注入。要注入 Dao,您需要通过ApplicationContext(弹簧)或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(); 
}

相关内容

  • 没有找到相关文章

最新更新