【问题标题】:verify object type with easymock使用 easymock 验证对象类型
【发布时间】:2009-08-13 17:32:41
【问题描述】:

我刚刚进入easymock的世界。我想问一下easymock是否只为接口模拟对象? 因此,在我努力理解的过程中,我编写了一个类来在 java 中生成唯一凭证。我显然不知道它将生成哪个值以在断言内容中使用。那么如何确保生成的凭证是 long 类型?

这里是函数

 public static Long generateID(int length) {
    logger.info("Calling generateID with specify length");
    Long result = null;

    if (length > 0) {
        StringBuffer id = new StringBuffer(length);
        for (int i = 0; i < length; i++) {
            id.append(NUMS[(int)Math.floor(Math.random() * 20)]);
        }
        result = Long.parseLong(id.toString());
    }

    return result;
}

这里是测试类

@Before
public void setUp() {
    mockgenerator = createMock(VGenerator.class);
}


/**
 * Test of generateID method, of class VGenerator.
 */
@Test
public void testGenerateID() {
   Long exp = (long)1;
   int length = 15;
    expect(mockgenerator.generateID(length)).equals(Long.class);
    replay(mockgenerator);
    long res = mockgenerator.generatedID(length);
    assertEquals(exp.class, res.class);
}

这对你来说可能看起来很棒,但我仍然对如何做到这一点感到困惑 感谢您的帮助

【问题讨论】:

  • 如果 generateID() 试图返回一个不长的东西,这个类甚至不会编译。

标签: java unit-testing junit easymock


【解决方案1】:

我相信你误解了easymock的使用方式, 调用 expect 告诉模拟对象,当你重放它时,应该调用这个调用。附加 .andReturn() 告诉模拟对象返回你放在那里的任何东西,在我的例子中是一个长值 1。 easymock 的重点是你不需要实现模拟接口来测试使用它的类。通过模拟你可以将一个类与它所依赖的类隔离开来,只测试包含的代码您当前正在测试的课程。

interface VGenerator {
     public Long generateID(int in);
}


@Before
public void setUp() {
    mockgenerator = createMock(VGenerator.class);
}


@Test
public void testGenerateID() {
     int length = 15;
     expect(mockgenerator.generateID(length)).andReturn(new Long(1));
     replay(mockgenerator);
     myMethodToBeTested();
     verify(mockgenerator);
}

public void myMethodToBeTested(){
    //do stuff
    long res = mockgenerator.generatedID(length);
    //do stuff
}

如果我误解了您的问题并且确实如此,easymock 是否仅模拟接口?那么答案是肯定的,Easymock 只模拟接口。阅读文档以获取更多帮助Easymock

【讨论】:

    【解决方案2】:

    如果返回类型是long 是绝对关键的,并且您想确保未来的更改不会无意中改变它,那么您不需要easymock。只需这样做:

    @Test
    public void TestGenerateIDReturnsLong()
    {
       Method method = 
          VGenerator.class.getDeclaredMethod("generateID", new Class[0]);
       Assert.Equals(long.Class, method.GetReturnType());
    }
    

    目前您正在生成VGenerator 的模拟实现,然后您测试模拟。这没有有用。单元测试的重点是测试一个真正的实现。那么现在您可能想知道 mock 有什么用?

    例如,假设VGenerator 需要在内部使用随机数生成器,而您在构造函数中提供了它(称为“依赖注入”):

    public VGenerator
    {
        private final RandomNumberGenerator rng; 
    
        // constructor
        public VGenerator(RandomNumberGenerator rng)
        {
           this.rng = rng;
        }
    
        public long generateID(length)
        {
           double randomNumber = this.rng.getRandomNumber();
           // ... use random number in calculation somehow ...
           return id;
        }
    }
    

    在实现VGenerator 时,您对测试随机数生成器并不真正感兴趣。您感兴趣的是VGenerator 如何调用随机数生成器,以及它如何使用结果来产生输出。您想要的是完全控制随机数生成器以进行测试,因此您创建了它的模拟 :

    @Test
    public void TestGenerateId()
    {
       RandomNumberGenerator mockRNG = createMock(RandomNumberGenerator.class);
       expect(mockRNG.getRandomNumber()).andReturn(0.123);
       replay(mockRNG);
    
       VGenerator vgenerator = new VGenerator(mockRNG);
       long id = vgenerator.generateID();
       Assert.Equals(5,id); // e.g. given random number .123, result should be 5
    
       verify(mockRNG);
    }
    

    【讨论】:

      【解决方案3】:

      EasyMock Class extension 可以模拟类。它是 EasyMock 的扩展。它仍然可以模拟界面,因此它几乎可以替代 EasyMock。

      但是,在您的情况下,您正在尝试模拟静态方法。静态方法不能被模拟,因为它们不能被重载。您需要类检测才能做到这一点,而 EasyMock 不这样做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-10
        • 2021-05-17
        • 1970-01-01
        • 2021-03-09
        • 1970-01-01
        • 1970-01-01
        • 2018-12-04
        • 2019-05-16
        相关资源
        最近更新 更多