Using Mockito with TestNG

后端 未结 3 1123
陌清茗
陌清茗 2021-02-09 06:33

I took a working test written for JUnit using Mockito and tried to adapt it to work with TestNG but oddly using TestNG only one test will work.

I think it is somehow rel

相关标签:
3条回答
  • 2021-02-09 07:22

    I'm not sure, if this answer fits to the questioners problem, because the mocks are not listed. But I'd like to re-state one comment from andy in the accepted answer, which helped me out on the same problem. Here are some more details and an example:


    public class B {
    
    private A a;
    
    B (A a) {
        this.a = a
    }
    
    // ...
    

    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.MockitoAnnotations;
    import org.testng.annotations.AfterMethod;
    import org.testng.annotations.BeforeMethod;
    import org.testng.annotations.Test;
    
    
    public class MyTest {
    
        @Mock
        A a;
    
        @InjectMocks
        B B;
    
        @BeforeMethod
        public void init() {
            MockitoAnnotations.initMocks(this);
        }
    
        @Test
        void test1() {
            // ...
            // b.toString();
            // b.getA().toString();
            // a.toString();
        }
    
        @Test
        void test2() {
            // ...
            // b.toString();
            // b.getA().toString();
            // a.toString();
        }
    
        @AfterMethod
        public void reset()
        {
            // Solution:
            b = null;
        }
    }
    

    Mockitos initMocks only re-initializes mocks, as reset only resets mocks. The problem is the class under test, which is annotated with @InjectMocks. This class, here named B is not initialized again. It is initialized for the first test with a mock of A, the mock of A is re-initialized but B still contains the first version of A.

    The solution is to reset the class under test manually with b = null at any plausible place (@AfterMethododer before initMocks). Then Mockito also re-inizialized the class under test B.

    0 讨论(0)
  • 2021-02-09 07:24

    You can also use MockitoTestNGListener it is similar to JUnit MockitoJUnitRunner or MockitoExtension.

    Example of code:

    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.testng.MockitoTestNGListener;
    import org.testng.annotations.Listeners;
    import org.testng.annotations.Test;
    
    import java.util.Map;
    
    @Listeners(MockitoTestNGListener.class)
    public class MyTest {
    
        @Mock
        Map map;
    
        @InjectMocks
        SomeType someType;
    
        @Test
        void test() {
            // ...
        }
    }
    
    0 讨论(0)
  • 2021-02-09 07:32

    There is a difference in the behaviour of these frameworks:

    • JUnit creates a new instance of class for every of its test methods. This means that the fields are not shared between tests.
    • But TestNG creates only one object and thus the state in fields is shared between to @Tests

    For Mockito you need to init mocks before every test method so that the state is not shared between two @Tests in TestNG:

    @BeforeMethod
    public void init() {
        MockitoAnnotations.initMocks(this);
    }
    

    For JUnit it works out of box because 2nd @Test has its own fields and its own mocks.

    0 讨论(0)
提交回复
热议问题