2011-02-06 236 views
10

我有这样一个类:测试代码

public final class Foo 
{ 
    public native int getBar(); 

    public String toString() 
    { 
     return "Bar: " + getBar(); 
    } 
} 

请注意:getBar()用JNI实现,该类是最后。我想写一个junit测试来测试toString()方法。为此,我需要模拟getBar()方法,然后运行原始的toString()方法检查输出。

我首先想到的是,这肯定是不可能的,但后来我发现PowerMock与支持根据功能列表最后的测试类和本地方法。但到目前为止,我没有成功。我管理的最好的东西是嘲笑完整的课程,但接下来测试测试了模拟的方法,而不是真正意义上的方法。

那么如何使用PowerMock从上面测试这个toString()方法?我更喜欢使用PowerMock Mockito,但如果这是不可能的,我用EasyMock来代替没有问题。

回答

8

找到它。我这样做的方式是正确的。我错过的唯一的事情是在调用toString()时告诉模拟对象调用原始方法。因此,它的工作原理是这样的:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ Foo.class }) 
public class FooTest 
{ 
    @Test 
    public void testToString() throws Exception 
    { 
     Foo foo = mock(Foo.class); 
     when(foo.getBar()).thenReturn(42); 
     when(foo.toString()).thenCallRealMethod(); 
     assertEquals("Bar: 42", foo.toString()); 
    } 
} 
+1

HI ......我不能添加 “时()” ..为什么..?你能告诉我使用Easymock – 2015-12-22 07:55:10

1

或者使用策略模式

public final class Foo 
    { 
     public IBarStrategy barStrategy; 

     ...... 
    } 

    interface IBarStrategy{ 
     int getBar(); 
    } 

当单元测试,注入模拟IBarStrategy实例,那么你可以测试Foo类。

+3

依赖注入对于代码重用和模块化是一件好事,但如果不需要,那么为什么我应该增加复杂性并放松我的类的API以提高可测性?但这不是重点。假设我不能更改测试主题,因此我无法将本地方法提取到接口中。 – kayahr 2011-02-07 06:24:05

3

或者使用JMockit动态部分嘲讽

import org.junit.*; 
import mockit.*; 

public class FooTest 
{ 
    @Test 
    public void testToString() 
    { 
     final Foo foo = new Foo(); 
     new Expectations(foo) {{ foo.getBar(); result = 42; }}; 

     assertEquals("Bar: 42", foo.toString()); 
    } 
}