Home > Blockchain >  Mokito/Java - Static Methods Mock
Mokito/Java - Static Methods Mock

Time:01-04

For example I have the following classes below:

public class TesteEstatico {

   public static String teste(){
      return "FOO";
   }

}

And I have a class that uses her method:

public class UsaTesteEstatico {

   public String metodoParaTeste1 (){
       return  TesteEstatico.teste()   " BAR ";
   }

   public String metodoParaTeste2 (){
       return  "FOO " TesteEstatico.teste()   " BAR ";
   }

}

Test class:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; 
import org.mockito.InjectMocks; 
import org.mockito.Mockito; 
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class) public class UsaTesteEstaticoTest {

   @InjectMocks
   UsaTesteEstatico usaTesteEstatico;

   @Test
   void teste1(){
       Mockito.mockStatic(TesteEstatico.class);
       Mockito.when(TesteEstatico.teste())
            .thenReturn("BANANA");

       String res = usaTesteEstatico.metodoParaTeste1();
       System.out.println(res);
   }

   @Test
   void teste2(){
       Mockito.mockStatic(TesteEstatico.class);
       Mockito.when(TesteEstatico.teste())
            .thenReturn("LARANJA");

       String res = usaTesteEstatico.metodoParaTeste2();
       System.out.println(res);

   }
}

Error I get when trying to run the tests:

org.mockito.exceptions.base.MockitoException: For TesteEstatico, static mocking is already registered in the current thread To create a new mock, the existing static mock registration must be deregistered

Versions of the libs that are in the project:

  • junit-jupiter 5.5.2
  • mockito-junit-jupiter 3.2.14
  • mockito-inline 3.2.14

Any idea how to solve this, i've tried a few things but nothing successful.

NOTE: I cannot change or add any new libraries as it is a restricted project.

CodePudding user response:

You should use try-with-resources block in each of the tests to close the mockStatic.

public class UsaTesteEstaticoTest {
    
    UsaTesteEstatico usaTesteEstatico = new UsaTesteEstatico();

    @Test
    void teste1(){
        try (var ms = Mockito.mockStatic(TesteEstatico.class)) {
            Mockito.when(TesteEstatico.teste()).thenReturn("BANANA");
            String res = usaTesteEstatico.metodoParaTeste1();
            System.out.println(res);
        }
    }

    @Test
    void teste2(){
        try (var ms = Mockito.mockStatic(TesteEstatico.class)) {
            Mockito.when(TesteEstatico.teste()).thenReturn("LARANJA");
            String res = usaTesteEstatico.metodoParaTeste2();
            System.out.println(res);
        }
    }
}

Note on mockStatic in @BeforeAll

Using @BeforeAll is a trap and bad advice. You should strive for independent tests that don't affect each other. This is not the case for mockStatic called in @BeforeAll, as stubbing from test methods outlive the test methods.

For example

// BAD CODE DONT USE
public class UsaTesteEstaticoTest {

    UsaTesteEstatico usaTesteEstatico = new UsaTesteEstatico();
    static MockedStatic<TesteEstatico> ms;

    @BeforeAll
    public static void init() {
        ms = Mockito.mockStatic(TesteEstatico.class);
    }

    @AfterAll
    public static void close() {
        ms.close();
    }


    @Test
    void teste1() {
        Mockito.when(TesteEstatico.teste()).thenReturn("BANANA");
        String res = usaTesteEstatico.metodoParaTeste1();
        System.out.println(res);
    }

    @Test
    void teste2() {
        String res = usaTesteEstatico.metodoParaTeste2();
        System.out.println(res);
    }
}

teste2 prints:

  • FOO BANANA BAR if run after teste1
  • FOO null BAR if run separately

This is precisely what you want to avoid.

CodePudding user response:

you need to use static block to mock it.

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;


@ExtendWith(MockitoExtension.class)
public class UsaTesteEstaticoTest {
    @InjectMocks
    UsaTesteEstatico usaTesteEstatico;

    @BeforeAll
    public static void init(){
        Mockito.mockStatic(TesteEstatico.class);
    }

    @Test
    void teste1(){

        Mockito.when(TesteEstatico.teste())
                .thenReturn("BANANA");

        String res = usaTesteEstatico.metodoParaTeste1();
        System.out.println(res);
    }

    @Test
    void teste2(){

        Mockito.when(TesteEstatico.teste())
                .thenReturn("LARANJA");

        String res = usaTesteEstatico.metodoParaTeste2();
        System.out.println(res);

    }
}
  •  Tags:  
  • Related