Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用模拟对象编写单元测试?_Java_Unit Testing_Mocking - Fatal编程技术网

Java 如何使用模拟对象编写单元测试?

Java 如何使用模拟对象编写单元测试?,java,unit-testing,mocking,Java,Unit Testing,Mocking,我读的模拟例子越多,我就越困惑 我有一个类方法eat(),它调用FatDude类eatThemAll() 现在,我想通过模拟FatDude类来测试classA eat()方法 public class MockFatDude extends FatDude { //override public String eatThemAll() { return "very full"; } } ------------- test -------------- publi

我读的模拟例子越多,我就越困惑

我有一个类方法eat(),它调用FatDude类eatThemAll()

现在,我想通过模拟FatDude类来测试classA eat()方法

public class MockFatDude extends FatDude {
   //override
   public String eatThemAll() {
      return "very full";
   }
}
-------------  test --------------
public class DoTest {

    public void runTest() {
         classA cl = new ClassA();
         String out = cl.eat();
         assertEqual(out, "very full");
    }
}
这个DoTest runTest()当然不会使用MockFatDude类。我可以考虑的一种方法是更改代码,以传递ClassA的FatDude to eat()方法,如下所示:

public class classA {

       public String eat(FatDude dude) {
            String result = dude.eatThemAll();
       }
   }
然后将我的测试方法更改为:

public class DoTest {

        public void runTest() {
             classA cl = new ClassA();
             String out = cl.eat(new MockFatDude());
             assertEqual(out, "very full");
        }
    }
但是正如你所看到的,我不得不修改源代码以满足我的需要。 这样做对吗?如果不允许我更改源代码怎么办? 我知道如果我应用TDD概念,更改源代码是可以的,但我想听听 如果我上面所展示的方法是正确的,那么请给出一些意见或建议。

mock和(DIP)是齐头并进的,在大多数语言中,mock通过接口解耦类的方式工作得最好

在您的实例中,这将在您不需要更改代码的情况下工作:(编辑:我的意思是,在将来,如果您以这种方式设计应用程序,您将不需要将代码更改为模拟依赖项:))

  • 抽象接口
  • 具体类fatude(和mockfatude)应该实现IDude接口
  • 提供一种机制,用于将IDude实例“设置”或注入classA-依赖注入(构造函数或get/set);或服务定位器模式最适合(替换具体的类工厂)

还请注意,许多模拟框架实际上允许您“动态”构建模拟具体类(参见MoQ等人),因此您可以在单元测试中直接创建MockFatDude的功能。

是的。由于单元测试,您直接偶然发现了一些好的设计。如果你仔细观察,你会发现你移除了classA和FatDude之间的耦合。现在,FatDude可以成为行为的接口,在需要时传递。ClassA不需要知道它得到了什么样的胖子,也不需要知道如何构造一个胖子(带奶酪汉堡?)


你的解决方案正是我应该做的。只要您了解更改代码以适应TDD的原因和好处/缺点,就没有错。

是java还是C#?你用什么工具?请添加适当的标签。谢谢。@maksymko:我不认为语言或工具对这个问题很重要,只是因为它是一种面向对象的语言。@calavera:我的意思是为了澄清更恰当的分类/过滤等,不是为了帮助回答这个问题。@maksymko:我没有使用像jmock或easymock这样的工具,因为我想了解什么是mock以及如何使用。大部分教程都使用模拟工具演示示例,这让人很难理解。@noonb:我认为他在示例解决方案中暗示了抽象,否则他可能需要重写。由于上面的代码看起来像Java而不是C#,我将在非DI环境中添加一个链接,您还可以在纯java中轻松地构建模拟对象,方法是在被测试的类上使用类似于getter注入的东西,并插入充当模拟的匿名内部类。
public class DoTest {

        public void runTest() {
             classA cl = new ClassA();
             String out = cl.eat(new MockFatDude());
             assertEqual(out, "very full");
        }
    }