【问题标题】:how to elegantly dependency inject a primitive boolean for testing?如何优雅地依赖注入原始布尔值进行测试?
【发布时间】:2014-06-19 00:12:24
【问题描述】:

我正在使用 Mockito 进行单元测试,因此,看起来我可以使用 @InjectMocks@Mock 注释注入某些对象。我假设我可以为对象类型 Booleans 执行此操作

但是,我似乎无法让它适用于原始 booleans。我该怎么做呢?或者什么框架允许这样做? (我实际上是在一个 Android 项目上)

例如:

class MethCook {
    private Laboratory mLab; // i can inject this
    private Assistant mJessePinkman; // this is injectable too
    private boolean mCanCookPureCrystal; // how do i access/inject this?

    private void cookBlueMeth() { ... }

    private void onTraumatized() {
        mCanCookPureCrystal = false;
        startMoppingAround();
        beDepressed();
        neverWantToCookAgain();
    }
}

注意:优雅意味着简洁和简洁,如...我不想在 getter/setter 之上使用@VisibleForTesting 来访问这个布尔值;因为这会将状态的可变性暴露给外部世界?

【问题讨论】:

  • 你为什么要注入一个布尔值?布尔值无法做任何有趣的事情。只需设置它。
  • @chrylis 如果可能的话,我不想将不必要的状态访问暴露给外部(来自其他人的意外突变)
  • 在实际使用中你会如何设置这个布尔值?
  • 我直接将它设置为 true 到一些私有方法,它可以做几件事。我会把这部分添加到我的问题中

标签: java android unit-testing dependency-injection


【解决方案1】:

如果有控制反转,(@Autowired/@Value/@Resource),反射就很容易了。

    @Before 
    public void init() {
        Field f = myMethCooking.getClass().getDeclaredField("mCanCookPureCrystal");
        f.setAccessible(true);
        f.set(myMethCooking, false);
    }

java-set-field-value-with-reflection!

【讨论】:

  • 经验法则是在没有其他方法之前不要使用反射,这里有更简单更好的方法 - 例如包私有设置器;)
【解决方案2】:

Mockito 是一个模拟框架,而不是一个注入框架。 @Mock 注释不支持模拟开发人员不拥有的东西,例如 boolean.class。

尝试在 JUnit 的 @Before 注释中设置布尔值,例如:

@Before public void inject_mCanCookPureCrystal() {
    myMethCooking.setMCanCookPureCrystal(false);
}

这是 Mockito 的增强请求数据库中的一个问题,它讨论了扩展注释,可能以一种可以与原语一起使用的方式:Mockito Issue 290

如果该值没有设置器,那么您将需要执行一个方法来根据需要预先设置它。许多测试人员会争辩说,如果某些东西不能直接在外部设置,那么它就不是类公共契约的一部分,无论如何都不应该通过注入、反射、注释或其他任何东西来设置。 (见https://stackoverflow.com/a/2811171/325452。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 2011-08-01
    相关资源
    最近更新 更多