如何将数据模型模拟注入spring控制器?

时间:2019-05-31 14:51:50

标签: java spring mockito spring-test

在单元测试中,我需要在弹簧@Controller中模拟数据模型实例,否则@RequestMapping方法的返回值会出错。

为此,我尝试了以下操作:

  1. 创建一个用户模型,该模型调用user.login()并需要返回“ true”
  2. 在LoginController中注入模拟对象
  3. 存根登录方法以返回true
  4. 在春季测试中使用MockMVC执行POST /登录
  5. 验证是否嘲笑了mockUser.login

这是控制器方法:

@RequestMapping(value = "/Login", method = RequestMethod.POST)
  public String updateUI(Locale locale, Model model, @RequestParam("username") String username,
      @RequestParam("hashedPW") String hashedPW, HttpServletRequest request) {
    model.addAttribute("username", username);
    user = new User(username, username, hashedPW.getBytes(), LoginHandler.getInstance());

    boolean loginResult = user.login();
    if(loginResult == true) {
      return "profile";
    }
    String output = "Failed login (" + username + ") requested, locale = " + locale;
    log(output);
    return "home";
  }

和我的注入模拟对象的初始化:

@Mock
  private User mockUser;

  @InjectMocks
  private LoginController injectedLoginController;


  @Before
  public void setup() throws ServletException {
    MockitoAnnotations.initMocks(this);
    mvc = MockMvcBuilders.standaloneSetup(injectedLoginController).build();
    LOGFILE = new File("logs/general.log");
  }

最后是单元测试:

@Test
  public void testLoginSuccess() throws Exception {
    String username = "Stefan";
    byte[] hashedPW = "".getBytes();
    when(mockUser.login()).thenReturn(true);
    ResultActions ra = mvc
        .perform(post("/Login").param("username", username).param("hashedPW", hashedPW.toString()))
        .andExpect(status().isOk());

    verify(mockUser).login();
  }

总的来说,我希望控制器处理的User对象具有模拟用户类型而不是User类型,并且login()方法被调用一次(相应地)并返回“ true”。

但是我得到的只是 “想要但不被调用:mockUser.login()  实际上,与该模拟游戏的互动为零。”

我很乐意为解决我的问题提供任何建议,因为我已经花了相当长的时间从事这项工作,但我似乎还不明白。

2 个答案:

答案 0 :(得分:0)

1):这似乎是一项IT测试。您不应强行进行任何注射。spring会这样做:

@InjectMocks
private LoginController injectedLoginController;

2):您需要监视控制器:

@SpyBean
private LoginController injectedLoginController;

3)您需要将User的创建移至控制器内部的包级方法:

user = createUser(username, username, hashedPW.getBytes(), LoginHandler.getInstance()); 


...

User createUser(...){
   return new User(username, username, hashedPW.getBytes(), LoginHandler.getInstance());
}

4):使该方法返回模拟的用户:

  doReturn(mockUser).when(injectedLoginController).createUser(...);
  when(mockUser.login()).thenReturn(true);

答案 1 :(得分:0)

如果您不想更改代码,可以从PowerMockito寻求帮助,这可以帮助模拟新对象的构建。

@RunWith(PowerMockRunner.class)
@PrepareForTest({User.class})
public class ControllerUnderTest {
  // here User is class for which we want to mock object creation
}

现在,让我们模拟对象

@Test
public void testLoginSuccess() throws Exception {
 ....
 User userMock = PowerMockito.createMock(User.class);

 PowerMockito.whenNew(User.class).withArguments(username, username, hashedPW.getBytes(), LoginHandler.getInstance()).thenReturn(userMock);

 expect(userMock.login()).andReturn(true);

 verify(mockUser).login();
 ...
}

有关powermock的更多详细信息,请检查此PowerMockito