Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

[Dúvida] Falha ao testar código 200 login controller

Estou com problemas para criar um mock para testar o método que segue no print destacado, depois que eu recebo os atributos, eu não consigo enviar o password (null), para eu validar o cenário de sucesso. Como que eu faço para ajustar no código essa configuração? Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Segue o trecho do código que eu criei para testar:

@Test
    @DisplayName("Deveria devolver código http 200, quando as informações estiverem válidas")
    @WithMockUser
    void efetuateLoginCenario2() throws Exception {
        var dadosAutenticacao = new DadosAutenticacao("user.test@plano.saude", "12345");

        var dadosToken = new DadosToken("$2a$12$1gu8/Allz2imTogT3O75ne/UArKM8UExUnhHRy4jRF2107qE6ZwSy");

        var response = mvc
                .perform(
                        post("/login")
                                .contentType(MediaType.APPLICATION_JSON)
                                .content(dadosAutenticacaoJson.write(dadosAutenticacao).getJson())
                )
                .andReturn().getResponse();

        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());

        var jsonRetorno = dadosTokenJson.write(dadosToken).getJson();

        assertThat(response.getContentAsString()).isEqualTo(jsonRetorno);
    }

Entendo que dessa forma a classe TokenService, como aprendemos no curso, não vai fazer o tratamento do token, seguindo as configurações que foram feitas. Porém, se eu criar o mock abaixo, ele espera um valor, que não consigo passar qual é e aí aumentou a minha dúvida na hora de testar...

when(tokenService.generateToken(any())).thenReturn(String.valueOf(dadosAutenticacao));

Poderiam me ajudar, por favor?

3 respostas

Olá, Alexandre.

Tudo bem?

Pelo que entendi, você está enfrentando um problema ao tentar testar o método de login na sua API, onde o password está sendo enviado como null e você gostaria de ajustar isso para testar o cenário de sucesso.

No trecho de código que você compartilhou, você está criando um objeto DadosAutenticacao com um usuário e senha válidos. No entanto, parece que o problema está relacionado com a maneira como o tokenService.generateToken está sendo mockado ou com a autenticação em si que não está sendo efetuada corretamente, resultando em um status HTTP 401 (Não Autorizado) ao invés de 200 (OK).

Vamos tentar ajustar o mock do tokenService para garantir que ele retorne um token válido quando um usuário e senha corretos são fornecidos. Além disso, é importante garantir que o AuthenticationManager esteja autenticando o usuário corretamente. Aqui está uma sugestão de como você pode ajustar seu teste:

1. Ajuste o Mock do TokenService: Certifique-se de que o mock do tokenService está retornando um token válido quando o método generateToken é chamado com um usuário autenticado.

// Mock do TokenService para retornar um token fictício
when(tokenService.generateToken(any(Usuario.class))).thenReturn("token_ficticio");

**2. ** Verifique a Autenticação: Certifique-se de que o AuthenticationManager está sendo chamado e está autenticando o usuário corretamente. Você pode adicionar um mock para AuthenticationManager para retornar uma autenticação bem-sucedida.

// Mock do AuthenticationManager para simular uma autenticação bem-sucedida
Authentication authentication = mock(Authentication.class);
when(authentication.isAuthenticated()).thenReturn(true);
when(authenticationManager.authenticate(any(Authentication.class))).thenReturn(authentication);

3. Atualize o Teste para Usar os Mocks: Certifique-se de que seu teste está usando os mocks corretamente e que o objeto DadosAutenticacao está sendo serializado corretamente para JSON.

@Test
@DisplayName("Deveria devolver código http 200, quando as informações estiverem válidas")
@WithMockUser
void efetuateLoginCenario2() throws Exception {
    var dadosAutenticacao = new DadosAutenticacao("user.test@plano.saude", "12345");

    // Mocks configurados anteriormente

    var response = mvc.perform(post("/login")
            .contentType(MediaType.APPLICATION_JSON)
            .content(dadosAutenticacaoJson.write(dadosAutenticacao).getJson()))
            .andReturn().getResponse();

    assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());

    var jsonRetorno = dadosTokenJson.write(new DadosToken("token_ficticio")).getJson();
    assertThat(response.getContentAsString()).isEqualTo(jsonRetorno);
}

Essas alterações devem ajudar a garantir que o cenário de sucesso seja testado corretamente, simulando a autenticação e a geração de token de forma adequada. Lembre-se de ajustar os nomes das variáveis e métodos conforme necessário para se alinhar com o seu código atual.

São apensas sugestões baseadas no contexto e no código que você compartilhou para tentar te ajudar, por favor tenta adaptar e ajustar se necessário.

Espero ter ajudado. Qualquer dúvida manda aqui. Bons estudos.

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.Bons Estudos!

Oi! Então, eu tentei rodar novamente, com as alterações sugeridas, mas retornou o erro abaixo. Como que eu consigo verificar para retornar um token válido para mockar, dentro do cenário de teste? Não estou conseguindo simular a autenticação, para testar o cenário. Como que eu faço para invocar?

Erro: java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "authentication" is null

Esta variável está recebendo o valor nula, que está dando o problema para o erro que estou tomando. Poderiam me ajudar neste cenário, como que eu faço para receber o token para simular dentro do teste, por favor?

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "authentication" is null

    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:166)
    at com.plano.saude.cadastro.controller.LoginControllerTest.efetuateLoginCenario2(LoginControllerTest.java:78)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    Suppressed: org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Misplaced or misused argument matcher detected here:

-> at com.plano.saude.cadastro.controller.LoginControllerTest.efetuateLoginCenario2(LoginControllerTest.java:78)

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(any());
    verify(mock).someMethod(contains("foo"))

This message may appear after an NullPointerException if the last matcher is returning an object 
like any() but the stubbed method signature expect a primitive argument, in this case,
use primitive alternatives.
    when(mock.get(any())); // bad use, will raise NPE
    when(mock.get(anyInt())); // correct usage use

Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.

        at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:86)
        at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:73)
        at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.afterTestMethod(ResetMocksTestExecutionListener.java:67)
        at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:487)
        at org.springframework.test.context.junit.jupiter.SpringExtension.afterEach(SpringExtension.java:278)
        ... 2 more
    @Test
    @DisplayName("Deveria devolver código http 200, quando as informações estiverem válidas")
    @WithMockUser
    void efetuateLoginCenario2() throws Exception {
        var dadosAutenticacao = new DadosAutenticacao("user.test@plano.saude", "12345");

        // Mock do TokenService para retornar um token fictício
        when(tokenService.generateToken(any(Usuario.class))).thenReturn("token_ficticio");

        // Mock do AuthenticationManager para simular uma autenticação bem-sucedida
        Authentication authentication = mock(Authentication.class);
        when(authentication.isAuthenticated()).thenReturn(true);
        when(authenticationManager.authenticate(any(Authentication.class))).thenReturn(authentication);

        var response = mvc
                .perform(
                        post("/login")
                                .contentType(MediaType.APPLICATION_JSON)
                                .content(dadosAutenticacaoJson.write(dadosAutenticacao).getJson())
                )
                .andReturn().getResponse();

        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());

        var jsonRetorno = dadosTokenJson.write(new DadosToken("token_ficticio")).getJson();

        assertThat(response.getContentAsString()).isEqualTo(jsonRetorno);
    }
solução!

Para esta solução e para mais estudos, acompanhem o link abaixo: https://cursos.alura.com.br/forum/topico-bug-erro-para-testar-token-classe-logincontroller-cenario-200-427672