java - 当参数为零时,如何通过模拟编写单元测试 :constructors

标签 java unit-testing junit4 jmockit jmock

我试图使用 jmocks 和 junit 编写单元测试。 (我的项目使用核心java-无框架-)当在无参数构造函数中初始化依赖项时,我无法通过模拟外部依赖项为我的某些类编写单元测试。

由于我无法提供实际的代码,尝试通过示例解释该场景

public interface Apple {

String variety();

}

实现。

public class MalgovaApple implements Apple {

  @Override
  public String variety() {
         return "Malgova";

  }

}

待测试类

public class VarietyChecker {
private Apple apple;

VarietyChecker(){
this.apple = new MalgovaApple();
// instead of new, a factory method is used in actual application
}

public String printAppleVariety(){
    String variety = apple.variety();
    if(variety.length() < 3){
       System.out.println("Donot use Code names- Use complete names");
       return "bad";
        }
       return "good";
}
}

使用 jmock 进行 Junit 测试

public class VarietyCheckerUnitTest{
Mockery context = new JUnit4Mockery();
@Before
public void setUp() throws Exception {
}

@After
public void tearDown() throws Exception {
}

@Test
public void test_VarietyChecker() throws Exception{

    final Apple mockapple = context.mock(Apple.class);

    VarietyChecker printer = new VarietyChecker();
    context.checking(new Expectations(){{
        oneOf(mockapple).variety();will(returnValue("as"));
    }});
    String varietyNameValid = printer.printAppleVariety();

    assertEquals("bad",varietyNameValid);


} }

此测试失败 - 模拟不起作用,值“因为”未注入(inject),测试类使用 MalgovaApple 执行...

现在,如果我们将以下构造函数添加到 VarietyChecker 并使用它的测试用例 - 它会给出预期的输出...

public VarietyChecker(Apple apple) {
    super();
    this.apple = apple;
}

并在单元测试中创建测试类对象,例如 VarietyChecker 打印机 = new VarietyChecker(mockapple);

仅仅出于测试目的而公开新的构造函数并不是一个好主意。毕竟据说你不应该仅仅为了测试而改变代码,更重要的是,恐怕我们已经写了“一些”(数量)代码......

我是否在 junit 或 jmock 中缺少一些东西,即使在无参数构造函数的情况下也可以进行模拟工作。或者这是简单的 junit 和 jmocks 的限制,我应该迁移到像 Jmockit/PowerMock

这样强大的东西吗?

最佳答案

您应该考虑两种选择。

  1. 按照您的描述使用构造函数参数。

    在这种情况下,您并不是“仅出于测试目的而公开新的构造函数”。通过允许调用者使用不同的工厂实现,您可以使您的类更加灵活。

  2. 不要 mock 它。

    在这种情况下,您声明使用不同的工厂是没有意义的。有时这没关系。但到那时,问题就发生了变化。而不是“我该如何 mock 这个?”现在你的问题是:“我从编写这个测试中得到什么?”您可能不会获得太多任何东西,并且编写测试可能根本没有多大意义。

    如果您不模拟它并认为单元测试仍然值得,那么您应该对代码的其他方面进行断言。要么是最终状态,要么是某些输出。在这种情况下,工厂调用成为不适合模拟的实现细节。

    重要的是不要陷入“单元测试一切”的心态。这是测试引起的设计损坏的一个原因。根据具体情况评估您的测试,确定它们是否为您提供任何真正的值(value)。不编写单元测试是一个有效的选择,有时甚至是合适的,即使这是您极力避免的选择。

只有您才能确定在这种情况下哪一个最有意义。由于我们正在讨论的是一个工厂对象,因此我可能倾向于前者。

关于java - 当参数为零时,如何通过模拟编写单元测试 :constructors,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30676048/

相关文章:

python - 在Python中模拟对象的构造函数

c# - 如何断言集合只包含一个具有给定属性值的元素?

c# - System.BadImageFormatException :Could not load file or assembly … incorrect format when trying to install service with installutil. 可执行文件

java - Spring MVC 测试加载 xml 文件时出错

java - 我如何在selenium中发送隐藏密码的 key

java - 在运行时更改日志级别而不重新启动服务器?

java - 几天后 GC 暂停变得很长

spring - Spring JUnit 测试中的自动模拟实例化

java - 两个 Maven 项目中的相同包、相同类(WAR 和 JAR)、类路径问题

java - 使用 VisualVM 堆转储计算 java 对象的内存使用情况与理论方法不符