Java:当一个字段没有公开时,我如何模拟该字段的方法?

2022-09-03 05:30:25

我正在使用Java 6,JUnit 4.8.1,并编写一个控制台应用程序。我的应用程序有一个未公开的成员字段...

public class MyApp { 
    ...
    private OpportunitiesService m_oppsSvc;

    private void initServices() { 
        …
        m_oppsSvc = new OpportunitiesServiceImpl(…);
    }
    ...
}

我想模拟一种行为,这样每当调用我的服务中的一个方法(例如)时,总是返回相同的结果。我该怎么做?该字段没有 setter 方法。我目前正在使用Mockito 1.8.4。是否可以使用Mockito或其他模拟框架执行此操作?m_oppsSvc.getResults()


答案 1

这是你想要的:

@RunWith(MockitoJUnitRunner.class)
public class MyAppTest { 

    @Mock private OpportunitiesService mocked_m_oppsSvc;
    @InjectMocks MyApp myApp;

    @Test public void when_MyApp_uses_OpportunititesService_then_verify_something() { 
        // given
        given( mocked_m_oppsSvc.whatever()).willReturn(...);

        // when
        myApp.isUsingTheOpportunitiesService(...);

        // then
        verify...
        assertThat...
    }
}

使用:Mockito 1.9.0BDD风格FEST-Assert AssertJ

希望对:)有所帮助


答案 2

既然你已经在使用mockito,为什么不直接使用反射:

@RunWith(MockitoJUnitRunner.class)
public class MyApp { 

    @Mock
    private OpportunitiesService m_oppsSvc;

    private MyApp myApp;


    @Before
    public void before() throws Exception {
       myApp = new MyApp();
       Field f = MyApp.class.getDeclaredField("m_oppsSvc");
       f.setAccessible(true);
       f.set(myApp, m_oppsSvc);
    }
}

这有点丑陋,但它会解决问题。请注意,这可能不是使用Mockito执行此操作的最有效方法,但它可以正常工作。

还有Powermock,它应该允许你使用Whitebox类来做到这一点。我不会深入讨论Powermock的全部细节,但这里是注入私有字段值的调用,它应该是一个模拟对象:

Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc);

推荐