简体   繁体   English

Mockito:用不同的方法覆盖模拟值

[英]Mockito: Override mock values in different methods

@RunWith(MockitoJUnitRunner.class)
public class Test {

     @Mock
     private SomeDependency<T> obj;

     @InjectMocks
     private SomeClass mainObj;

     @Test
     public void dependencyShouldBeNotNull() {
       //here I need one value of SomeDependency obj
       assertEquals(2, mainObj.method())
     }

     @Test
     public void dependencyShouldBeNull() {
       //here I need SomeDependency obj to be null
       assertEquals(1, mainObj.method())
     }

Main class: 主要课程:

class SomeClass {
      private SomeDependency<T> field;

      public int method() {
         if(field==null)
            return 1;
         else
            return 2;
      }
}

And my question: how to override value of mock according to different methods needs? 而我的问题是:如何根据不同的方法需要覆盖mock的值?

Edited In main SomeClass I have code like this: 编辑在主SomeClass我有这样的代码:

if (obj != null) {
       //perform some actions
    }

The easiest way to do it is with 2 test classes instead of one because when it executes your test methods it is already too late since the mock has already been injected (unless you use refection which should be avoided). 最简单的方法是使用2个测试类而不是1个测试类,因为当它执行测试方法时已经太晚了,因为模拟已经被注入(除非你使用应该避免的反射)。

The first test 第一次测试

@RunWith(MockitoJUnitRunner.class)
public class Test1 {
    @Mock
    private SomeDependency<T> obj;

    @InjectMocks
    private SomeClass mainObj;

    @Test
    public void dependencyShouldBeNotNull() {
        //here I need one value of SomeDependency obj
        assertEquals(2, mainObj.method());
    }
}

The second test 第二次测试

@RunWith(MockitoJUnitRunner.class)
public class Test2 {
    @InjectMocks
    private SomeClass mainObj;

    @Test
    public void dependencyShouldBeNull() {
        //here I need SomeDependency obj to be null
        assertEquals(1, mainObj.method());
    }
}

If you want to do it with only one test class, it is still possible but it is more like a hack because you want a conditional injection which is not a conventional approach, so you will need to inject the mocks programmatically with MockitoAnnotations.initMocks(obj) . 如果你只想用一个测试类来做它,它仍然是可能的,但它更像是一个黑客,因为你想要一个不是传统方法的条件注入,所以你需要用MockitoAnnotations.initMocks(obj)以编程方式注入MockitoAnnotations.initMocks(obj)

Instead of injecting the mocks directly into the test class, we need to rely on wrapper classes that will contain or not the field obj , if not present nothing will be injected so it will be null otherwise you will have a mock injected. 我们需要依赖包含或者不包含字段obj包装类,而不是将包含的类包含在包含或不包含字段obj ,如果不存在则不会注入任何内容,因此它将为null否则您将注入模拟。

public class TestInjectMocks {

    /**
     * Small interface that will be implemented by the wrapper classes
     * only used to get the main class
     */
    public interface TestConfig {
        SomeClass getSomeClass();
    }

    @Test
    public void dependencyShouldBeNotNull() {
        // This class will allow to get an instance of SomeClass 
        // with the field injected
        TestConfig obj = new TestConfig() {
            @Mock
            private SomeDependency<T> obj;
            @InjectMocks
            private SomeClass mainObj;

            @Override
            public SomeClass getSomeClass() {
                return mainObj;
            }
        };
        MockitoAnnotations.initMocks(obj);
        SomeClass mainObj = obj.getSomeClass();
        //here I need one value of SomeDependency obj
        assertEquals(2, mainObj.method());
    }

    @Test
    public void dependencyShouldBeNull() {
        // This class will allow to get an instance of SomeClass 
        // without the field injected
        TestConfig obj = new TestConfig(){
            @InjectMocks
            private SomeClass mainObj;
            @Override
            public SomeClass getSomeClass() {
                return mainObj;
            }
        };
        MockitoAnnotations.initMocks(obj);
        SomeClass mainObj = obj.getSomeClass();
        //here I need SomeDependency obj to be null
        assertEquals(1, mainObj.method());
    }
}

NB: As we call MockitoAnnotations.initMocks(obj) explicitly the annotation @RunWith(MockitoJUnitRunner.class) is not needed anymore. 注意:当我们明确地调用MockitoAnnotations.initMocks(obj) ,不再需要注释@RunWith(MockitoJUnitRunner.class)

Based on what you've posted, I recommend using the 'Mockito.when()' method for the first method, then setting obj = null; 根据您发布的内容,我建议对第一种方法使用'Mockito.when()'方法,然后设置obj = null; as @Seelenvirtuose suggests. 正如@Seelenvirtuose所说。 If that doesn't work, you might want to pass in a different Mocked out object which is initialized to null. 如果这不起作用,您可能希望传入一个初始化为null的不同Mocked out对象。 See this example. 这个例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM