【问题标题】:Why doesn't dynamic partial mocking work for JMockit's @Injectable?为什么动态部分模拟对 JMockit 的 @Injectable 不起作用?
【发布时间】:2015-04-07 15:10:28
【问题描述】:

在下面没有记录Expectations 的测试用例中,我希望动态部分模拟功能将用于AB 字段,它们在UnitToTest 中使用@Injectable 初始化.但相反,总是模拟方法调用。只有对静态部分模拟使用无效的过滤器值,才能调用真正的方法:

@Service
class A {
 public String doSomething() {  return "doSomething";   }
 public String doSomethingElse() {  return "doSomethingElse";   }
}

@Service
class B {
 public String doSomething() {  return "doSomething";   }
 public String doSomethingElse() {  return "doSomethingElse";   }
}

@Service
class UnitToTest {
 @Autowired B b;
 @Autowired A a;
 public B getB() {  return b;   }
 public A getA() {  return a;   }
}

public class TestClass {
 @Tested    UnitToTest unit;
 // @Mocked({ "someInvalidFilter()" })
 @Injectable    A a;
 // @Mocked({ "someInvalidFilter()" })
 @Injectable    B b;

 @Test
 public void test() {
    // actual return value is always null if no invalid static partial
    // mocking filters are specified above
    assertEquals("doSomething", unit.getA().doSomething());
    assertEquals("doSomethingElse", unit.getA().doSomethingElse());
    assertEquals("doSomething", unit.getB().doSomething());
    assertEquals("doSomethingElse", unit.getB().doSomethingElse());
 }
}

对我来说,使用 JMockit 进行动态部分模拟似乎不适用于 @Injectables。这是已知的限制吗?

【问题讨论】:

  • 示例测试中没有动态部分模拟;为此,您需要有一个“new Expectations(a, b) { ... }”期望记录块。但是“a”和“b”应该是真实的实例,而不是模拟的实例。
  • 感谢您的回答。然而,这意味着没有依赖注入可用。相反,我将不得不使用 Deencapsulation.setField()。是否计划扩展 Mocking 框架以支持 @Injectables 的部分动态模拟?或者至少我可以在以后的版本中依赖上述解决方法的支持吗?
  • 部分模拟和@Injectable 的注入是模拟API 的两个完全不同的部分。我不认为我明白你想说什么;如果你能解释一下你实际上要测试的是什么,那就容易多了。
  • 这个想法是使用@Injectables 作为@Autowired 字段来简化单元测试。并且仅当 Expectations 被记录或使用 Mockup 时,我希望现有的行为被嘲笑。如果不使用这些,我将依赖真实方法的调用。所以在上面的测试用例中调用AB的方法,应该使用真正的方法。

标签: unit-testing jmockit


【解决方案1】:

@Injectables 总是被注入到@Tested 对象中,假设可以找到匹配的字段或构造函数参数;注入过程甚至会考虑 DI 注释,例如 @Inject@Autowired

然而,@Injectable 实例总是被创建为未初始化(即没有状态)和完全模拟实例。另一方面,部分模拟适用于您在测试中自己实例化(和初始化)的真实实例。

所以,您似乎要求的是,可以将所说的真实实例(部分模拟或不模拟)注入到@Tested 对象中。实际上,这不受支持(除非通过调用 Deencapsulation.setField),因为用户从未提出过激励用例。

也就是说,如果将示例测试更改为以下内容,则示例测试将通过:

public class TestClass {
    @Tested(fullyInitialized = true) UnitToTest unit;

    @Test
    public void test() {
        assertEquals("doSomething", unit.getA().doSomething());
        assertEquals("doSomethingElse", unit.getA().doSomethingElse());
        assertEquals("doSomething", unit.getB().doSomething());
        assertEquals("doSomethingElse", unit.getB().doSomethingElse());
    }
}

以上是集成测试,但不是单元测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    相关资源
    最近更新 更多