Java:当该字段未公开时,如何模拟字段的方法?

Dav*_*ave 14 java junit unit-testing mockito

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

public class MyApp { 
    ...
    private OpportunitiesService m_oppsSvc;

    private void initServices() { 
        …
        m_oppsSvc = new OpportunitiesServiceImpl(…);
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我想模拟一个行为,这样无论何时调用我的服务中的一个方法(例如m_oppsSvc.getResults()),总是返回相同的结果.我怎么做?这个领域没有setter方法.我目前正在使用Mockito 1.8.4.是否有可能使用Mockito或其他一些模拟框架?

Bri*_*ice 12

这就是你想要的:

@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...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

希望有帮助:)

  • @InjectMocks也可以注入私有字段. (3认同)

Mat*_*att 8

鉴于你已经在使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这有点难看,但它会起作用.请注意,这可能不是使用Mockito执行此操作的最有效方法,但它可以正常工作.

还有Powermock应该允许你使用Whitebox类这样做.我不会深入了解Powermock的所有细节,但这里是注入私有字段值的调用,它应该是一个模拟对象:

Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc);
Run Code Online (Sandbox Code Playgroud)


mun*_*ngm 6

你应该考虑尝试模仿私人领域的气味.也就是说,表示您要执行的操作不正确或者您的代码当前结构不正确.您应该只需要模拟公共方法或注入依赖项

在您给出的代码中,您应该考虑注入OpportunitiesService,如下所示:

public class MyApp { 
    ...
    private OpportunitiesService m_oppsSvc;

    public MyApp(OpportunitiesService oppsSvc) {
        this.m_oppsSvc = oppsSvc;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

在您的测试中,您可以按如下方式注入模拟:

OpportunitiesService mockOpportunitiesService =
    Mockito.mock(OpportunitiesService.class);
Mockit.when(mockOpportunitiesService.someMethod()).thenReturn(someValue);
MyApp app = new MyApp(mockOpportunitiesService);
Run Code Online (Sandbox Code Playgroud)