2011-12-15 92 views
5

我在写一个测试类来测试我的'ImporterService'类。该服务读取一个InputStream并从其数据创建一个Object。 Object,在这个例子中是一个Builder类,在'ImporterService'类中被实例化。为了测试我的'ImporterService'类,我需要验证Builder类上的调用。为此,我想使用Mocking框架,但是如何在'ImporterService'之外创建'Builder'对象的模拟实例?嘲笑内部实例化对象

我“ImporterService”类的方法是这样的:

 


    public Builder importFrom(BufferedReader reader) throws IOException { 
     String someValue = readFrom(reader); 
     Builder builder = new Builder(); // I need to mock this Builder object... 
     builder.someMethod(someValue);  // to see of a method is called with the expected value 
    } 
 

我在想移动的生成器类的创建成一个受保护的方法,我可以在测试的设置覆盖。但是这个解决方案对我来说似乎不是很好,因为'ImporterService'类泄漏了一些内部逻辑,并且可以用其他我不想要的类重写方法。

回答

2

如果你使用任何依赖注入库(如Spring),你可以注入模拟对象,而不是生成器来ImporterService类。或者你可以用调用工厂代替调用构造函数,并使用工厂,返回测试代码中的模拟。

+0

如果使用好的模拟框架,你不需要在你的单元测试的另一个DI框架中。除非你正在测试你的布线 – 2011-12-15 09:48:50

0

假设你正在使用jMockt(我本电子书籍模拟框架),你将能够做到以下几点:

@Test 
    public void testFoo(@Mocked Builder builder) { 
     new Expectations() { 
      { 
       new Builder(); 
       returns(builder); 

       builder.setSomemethod() 
       ... 
      } 
     }; 

     assertSame(builder,impoertesService.importFrom(...)); 
    } 
0

有些嘲弄的框架,例如PowerMock可以模拟对象的构造。通过这样做

public Builder importFrom(BufferedReader reader, Builder builder) throws IOException { 

您可以通过从测试情况下,任何虚拟实现:

0

你可以改变函数签名这样的事情。这是依赖注入的一种方式。

依赖注入的想法是要求所有的依赖关系,如果一个类/函数这样做,代码变得高度可测试。

1

是的,你可以或做如你所说:

创建一个用于创建对象Builder,并将其分配给读取器类的工厂类。在你的单元测试中,模拟这个工厂并强制它建立一个你选择的Builder,你可以在你的单元测试中检查方法调用。

下面是使用EasyMock展示如何实现这样一个例子:

public class Reader{ 
    private BuilderFactory factory = new BuilderFactory(); // Use production factory by default 
    public Builder importFrom(BufferedReader reader) throws IOException { 
     String someValue = readFrom(reader); 
     Builder builder = factory.buildBuilder(); 
     builder.someMethod(someValue);  // to see of a method is called with the expected value 
    } 
} 

在单元测试中,你执行以下操作:

Reader classUnderTest = new Reader(); 
BuilderFactory fakeFactory = EasyMock.createNiceMock(BuilderFactory.class); 
Builder builder = EasyMock.createMock(Builder.class); 
EasyMock.expect(fakeFactory.buildBuilder()).andReturn(builder); 
builder.someMethod("value here"); 
EasyMock.expectLastCall().once(); 
EasyMock.replay(fakeFactory, builder); 
classUnderTest.importFrom(bufferReader); 
// Very that all calls were correctly performed on the builder 
EasyMock.verify(builder);