为什么有些@Mock对象上没有mockito拦截器?

cidc1ykv  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(88)

我正在为一些遗留代码编写Junits,我意识到当我使用@Mock注解模拟我的依赖关系时,一些模拟的对象似乎有一个与之关联的mockito拦截器,而有些则没有。我缺乏计算机编程的基础知识,任何帮助都很感激。

//Did not work, because of lack of @InkectMocks, 
//see that I create a new object of class to test.
    public class foo {

        ClassInTest classInTest;
        AutoCloseable mocks;

        @Mock
        Animal animal;
        @Mock
        Bike vehicle;

        @Before
        public void init() {
            mocks = openMocks(this);
            classInTest = new ClassInTest();
        }

        @After
        public void teardown() throws Exception {
            mocks.close();
        }

        @Test
        public void dogRidesBikeTest() {
            classInTest.checkIfAnimalRidesVehicle(new Dog(), new Bike());
        }
    }

    public interface Animal {
        public String getName();
        public String doSomething();
    }

    public class Dog implements Animal {
        @Override
        public String getName() {
            return "Dog";
        }
        @Override
        public String doSomething() {
            return "Did something";
        }
    }

    public interface Vehicle {
        public String getName();
        public String doSomething();
    }

    public class Bike implements Vehicle {
        @Override
        public String getName() {
            return "Bike";
        }
        @Override
        public String doSomething() {
            return "Did something";
        }
    }
    
    
    public class ClassInTest {
        public boolean checkIfAnimalRidesVehicle(Animal animal, Vehicle vehicle) {
            vehicle.doSomething();
            remoteMagic(animal, vehicle);
            return false;//dogs don't ride bikes!
        }

        public void remoteMagic(Animal animal, Vehicle vehicle) {
            //magic magic magic
        }
}

字符串
screenshot showing that one of the objects created using @Mock has an interceptor and the other does not

//This is an example of code that works, 
//in line with @Lesiak's answer, the lack of a $MockitoMock$ 
//definition on a mock object should not stop you from being able 
//to stub methods/interact with that mock in any way.
public class FooBarTest {
    @InjectMocks
    FooBar fooBar;
    @Mock
    List<String> mockList;
    @Mock
    CosmosAsyncContainer mockAsyncContainer;
    @Mock
    CosmosContainerResponse mockCosmosContainerResponse;
    AutoCloseable autoCloseable;
    @Before
    public void setup() {
        autoCloseable = openMocks(this);
    }
    @After
    public void tearDown() throws Exception {
        autoCloseable.close();
    }
    @Test
    public void test() {
        Mono<CosmosContainerResponse> raft = Mono.just(mockCosmosContainerResponse);
        when(mockList.size()).thenReturn(3);
        when(mockAsyncContainer.read()).thenReturn(raft);
        var result = fooBar.helloWorld();
        verify(mockList).size();
        verify(mockAsyncContainer).read();
        assertEquals(result, raft);
    }

}
public class FooBar {
    List<String> goodList;
    CosmosAsyncContainer goodContainer;

    public Mono<CosmosContainerResponse> helloWorld() {
        assertEquals(3, goodList.size());
        Mono<CosmosContainerResponse> raft;
        try {
            raft =  goodContainer.read();
        } catch (Exception ex) {
            raft = Mono.empty();
            System.out.println("gotcha!!");
        }
        return raft;
    }
}


我用mockSomething(这是一个有一个与之关联的拦截器的接口)模拟一个接口,用mockSomethingElse(这是一个没有与之关联的拦截器的类)对象模拟一个类,这两者的区别是什么?
当我在测试“dogRidesBikeTest”上放置一个调试点并观察到目前为止在测试上下文中创建的对象时,我观察到其中一个对象上有一个mockito拦截器,而另一个没有。
如果没有拦截器会影响方法存根(我希望它会),如果是的话,我如何解决这个问题。

  • 编辑:*

1.修复了在新代码示例中无法在我的模拟上存根方法的错误/原因。
1.最初的问题“为什么在一些mock对象上没有mockito拦截器”已经由@Lesiak回答
1.在任何mock对象上缺少$MockitoMock$指定应该不会干扰您与mock交互的方式,前提是您正确设置了测试/mock。

xxb16uws

xxb16uws1#

您正在使用mockito-inline,它会更改构造mock的方式:
这个替代的mock maker使用Java instrumentation API和子类化的组合,而不是创建一个新的类来表示mock。
InlineByteBuddyMockMaker javadoc说道:
这个mock maker在创建mock时会尽最大努力避免创建子类。否则,它将使用org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker创建mock类。这意味着以下条件为真

class Foo { }
assert mock(Foo.class).getClass() == Foo.class;

字符串
除非满足以下条件中的任何一个,否则在这种情况下,mock生成器返回到子类的创建。

  • 要模拟的类型是抽象类。
  • 模拟被设置为需要额外的接口。
  • mock被显式设置为支持序列化

在代码中:

  • Animal是一个接口,因此使用了子类化
  • Bike是一个具体的类,因此它使用检测

这两个模拟都是功能齐全的(stubbing工作等),但可以检测到差异,正如您已经注意到的那样。
另外,请注意,您没有将模拟传递给测试中的类--这是内部的吗?

相关问题