Как ввести макет модели данных в контроллер пружины? - PullRequest
0 голосов
/ 31 мая 2019

В моих модульных тестах мне нужно смоделировать экземпляр модели данных в пружине @Controller, иначе возвращаемое значение метода @RequestMapping будет неверным.

Чтобы сделать это, я попытался сделать следующее:

  1. Создание пользовательского макета, который вызывает user.login () и должен возвращать «true»
  2. Вставить фиктивный объект в LoginController
  3. Остановить метод входа вверните true
  4. Выполните POST / Login с MockMVC из весеннего теста
  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, который обрабатывается контроллеромиметь тип mockUser вместо User и метод login (), который вызывается один раз (соответственно) и возвращает «true».

Но все, что я получаю, это «Требуется, но не вызывается: mockUser.login ()На самом деле, было нулевое взаимодействие с этимк. "

Я благодарен за любые предложения по решению моей проблемы, так как я работаю над этим уже довольно давно, и, похоже, я не понимаю хитрости.

Ответы [ 2 ]

0 голосов
/ 01 июня 2019

Если вы не хотите изменять свой код, вы можете обратиться за помощью к 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

0 голосов
/ 31 мая 2019

1) Похоже, это ИТ-тест. Вы не должны форсировать инъекцию. Пружина делает это:

@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);
...