【问题标题】:Asserting that a JMockit expectation result is the same instance as constructed断言 JMockit 期望结果与构造的实例相同
【发布时间】:2016-03-29 20:16:44
【问题描述】:

这是一个从现实生活中剥离出来的方法......真正的方法做其他事情,但我已经将一些奇怪的行为缩小到这几行。考虑一种尝试从java.util.Date... 创建java.sql.Timestamp 的方法(不要介意我在此方法中做错了什么;这不是重点):

public class MyTest {

    public Timestamp convertDateToTimestamp(Date d) {
        long l = d.getTime();
        Timestamp ts = new Timestamp(l);
        return ts;
    }

}

所以我为此方法编写了以下 JMockit JUnit 测试用例:

@RunWith(JMockit.class)
public class MyTestTest {

    @Tested MyTest test;

    @Test
    public void testConvertDateToTimestamp(@Mocked final Timestamp ts, @Mocked final Date d) throws Exception {
        new Expectations() {
            {
                d.getTime(); result = 8675309l;
                new Timestamp(8675309l); result = ts;
            }
        };

         Timestamp retval = test.convertDateToTimestamp(d);
         assertThat(retval, sameInstance(ts));
    }

}

注意最后一行的断言...我想我应该确定我得到的实例与我的构造函数创建的实例完全相同。

这个测试返回一个非常奇特的结果:

java.lang.AssertionError: 
Expected: sameInstance(<java.sql.Timestamp@6e3c1e69>)
     but: was <java.sql.Timestamp@6e3c1e69>
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at com.example.dcohl.MyTestTest.testConvertDateToTimestamp(MyTestTest.java:32)
...

谁能解释一下?我的断言失败了,因为它期待Timestamp 的一个实例,但它却得到了......与Timestamp 完全相同的实例?

现在,如果我检查是否相等,使用is(ts) 而不是sameInstance(ts),我的测试就会成功。是否是同一个对象并不重要;平等就足够了。但这是一个令人头疼的结果......

【问题讨论】:

  • 通过使用调试器可以看到retvalts 是两个不同的对象,尽管toString 方法为两者生成相同的字符串。

标签: java junit jmockit hamcrest


【解决方案1】:

当一个测试记录了一个构造函数期望比如new Timestamp(8675309l); result = ts;,它仅仅意味着未来通过匹配构造函数调用创建的Timestamp实例将在逻辑上等价于ts模拟实例(即它们将具有相同的模拟在ts 上记录/验证的行为)。这并不意味着它们将是相同的实例;它们仍将是新实例。

【讨论】:

  • 那么有没有办法确保我传递的是新构建的Timestamp,而不是来自其他来源的Timestamp
  • 是:从测试中调用convertDateToTimestamp 两次,通过相同的Date,并检查返回的引用指向不同的实例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-26
  • 2016-10-04
  • 1970-01-01
  • 2016-06-24
相关资源
最近更新 更多