easymock教程-创建stub对象

easymock教程-创建stub对象


    前面教程中有个章节讨论到mock和stub的概念差别,一般来说easymock如其名所示,主要是用来做mock用的,但是easymock中也提供有对stub的支持, 主要体现在andStubAnswer(),andStubDelegateTo(),andStubReturn(),andStubThrow()和asStub()等方法的使用上。

    我们来看一个实际使用的例子:

 

     public   class  Business  {
        
private Service     service;

        
private StubService stubService;

        
public void execute1() {
            
if (service.execute()) {
                stubService.method1();
            }

        }


        
public void execute2() {
            
if (service.execute()) {
                stubService.method2();
            }

        }


        
public void execute3() {
            
if (service.execute()) {
                stubService.method1();
                stubService.method2();
            }

        }


        
public void setStubService(StubService stubService) {
            
this.stubService = stubService;
        }


        
public void setService(Service service) {
            
this.service = service;
        }

    }


    
private   interface  Service  {
        
public boolean execute();
    }


    
private   interface  StubService  {

        
public String method1();

        
public String method2();
    }

    这里的Business类依赖到Service和StubService,execute1() / execute2() / execute3() 是我们需要测试的三个方法,相同点都是必须调用service.execute(),不同点在于其后对stubService的调用各不相同。而我们假设在这里我们只关心Business类对Service的调用是否如预期,不关心对于StubService的调用,只要程序可以继续运行就可以了。

    一个正统的做法是手工写一个StubService的stub 实现,例如:

private   class  StubServiceImpl  {
 
public String method1() {
  
return "";
 }


 
public String method2() {
  
return "";
 }

}


    但是如果这个接口复杂方法众多,则这个stub类不得不实现所有的其他方法,即使完全用不到,因为java的语法限制。

    可以这样使用easymock来实现stub:

 

public   class  BusinessTest  {

    
private Business      business;

    
private IMocksControl mocksControl;

    
private Service       service;

    @Before
    
public void init() {
        business 
= new Business();
        business.setStubService(prepareStubService());
        mocksControl 
= EasyMock.createStrictControl();
        service 
= mocksControl.createMock("service", Service.class);
        business.setService(service);
    }


    
private StubService prepareStubService() {
        StubService service 
= EasyMock.createMock("stubService", StubService.class);
        service.method1();
        EasyMock.expectLastCall().andStubReturn(
"");
        service.method2();
        EasyMock.expectLastCall().andStubReturn(
"");
        EasyMock.replay(service);
        
return service;
    }


    @Test
    
public void testExecute1() {
        EasyMock.expect(service.execute()).andReturn(
true);
        mocksControl.replay();
        business.execute1();
        mocksControl.verify();
    }


    @Test
    
public void testExecute2() {
        EasyMock.expect(service.execute()).andReturn(
false);
        mocksControl.replay();
        business.execute2();
        mocksControl.verify();
    }


    @Test
    
public void testExecute3() {
        EasyMock.expect(service.execute()).andReturn(
true);
        mocksControl.replay();
        business.execute3();
        mocksControl.verify();
    }

}

 

    在方法prepareStubService()中,我们通过easymock创建了一个mock对象,然后和普通mock对象一样记录了期望的行为。不同的是用andStubReturn()替代了andReturn().

    然后我们直接调用EasyMock.replay(service),注意在这个测试案例中,我们另外创建了一个mocksControl并通过这个mocksControl创建了我们关注的Service接口的mock对象,它的record/replay/和verify()是和StubService完全分离的。这样做的好处是在execute1() / execute2() / execute3()的测试案例中,我们完全不必额外关心这个stub,所有的事情在init()函数中就已经准备好了。这样做的好处显而易见,execute1() / execute2() / execute3()的测试案例中,代码和测试逻辑都简单了。

    最后总结,在适当的时候使用easymock来创建stub对象,对于简化测试还是能有所帮助的。

你可能感兴趣的:(easymock教程-创建stub对象)