如何使用mockito来评估测试方法中的方法

时间:2016-08-23 09:30:56

标签: java unit-testing mockito spy


我正在为控制器方法实现一个测试用例。控制器方法如下所示,

public class LoginController{
   public String register(String token){
     //some logic 
     loginService.delete(String token);
    //some logic
   return "xxxx";
   }
}

我正在实现测试用例来测试寄存器方法,我不希望评估方法delete。 (delete方法是返回void的服务方法)。我做了一些研究,并在我的测试方法中使用下面的代码来不评估delete方法,但是当我调试它时仍然在delete方法中。任何人都可以指出我做错了什么。

public class LoginControllerTest{
   private loginService loginServiceMock;

   @Test
   public void testRegister(){
      loginServiceMock = new loginServiceImpl();
      loginService spy = spy(loginServiceMock);
      doNothing().when(spy).delete(any(String.class));
      //calling the controller method 
   }
}

3 个答案:

答案 0 :(得分:1)

LoginController重构为

之类的内容
public class LoginController {
    private LoginService loginService;

    public LoginController(LoginService loginService) {
        this.loginService = loginService;
    }

    public String register(String token){
        //some logic 
        loginService.delete(token);
        //some logic
        return "xxxx";
    }
 }

 public interface LoginService {
     void delete(String token);
 }

然后在你的测试中

public class LoginControllerTest {
   private LoginController loginController;

   @Test
   public void testRegister(){
      loginController = new LoginController(t -> {});

      loginController.register("foo");

      //do some assertion
   }
}

我知道这不是你(可能)预期的那种解决方案,但它解决了你的问题(真正的delete不再被调用了。)

此解决方案的其他优点:

  • 代码更加分离,更易于维护
  • 上述直接后果:代码变得更容易测试
  • 上述直接后果:您不需要做复杂的事情,不再需要模拟

答案 1 :(得分:0)

spy的全部概念是,它允许您在实际实例上调用和验证方法。因此,如果你调用一个间谍实例方法,它实际上会在实际实例上调用该方法,除非它被模拟。

对于您的情况,您需要使用mock代替spy

@RunWith(MockitoJUnitRunner.class)
public class LoginControllerTest{

   @InjectMocks
   private LoginController controller;

   @Mock
   private loginService loginServiceMock; 


   @Test
   public void testRegister(){      

      doNothing().when(loginServiceMock).delete(anyString()));
      //calling the controller method 
      String value = controller.register("mytoken");
      verify(loginServiceMock,times(1)).delete(anyString());
   }
}

答案 2 :(得分:0)

只要将loginService spy对象注入您正在测试的LoginController,您所做的就应该正常工作。从您发布的代码中看不到这一点。

有两个原因会让控制器调用真正的登录服务方法:

  1. 您忘记将间谍注入控制器:loginControllerToTest = new LoginController(spy)loginControllerToTest.setLoginService(spy)

  2. loginService.delete()是一种静态方法,在这种情况下,您需要重构代码以删除静态依赖项或使用其他模拟工具(如powermock)。有关详细信息,请参阅this question