【问题标题】:Want spring bean to have mocked as well as real implementations+spring+mockito想要 spring bean 模拟以及真正的实现+spring+mockito
【发布时间】:2015-01-28 07:08:40
【问题描述】:

我有一个班级 Service 我想测试它。基本上,我面临一个问题,因为我希望 Service 对象被部分模拟。只有obj1 应该被嘲笑,其他的合作者应该是真实的。我的代码是这样的:

@Component
public class Service {

    @Autowired
    Object1 obj1;

    @Autowired
    Object2 obj2;

    public void validate(){
        obj1.isValid();
        obj2.isActive();

    }
}

现在在测试上述Service 类的验证方法时,我想在调用obj2 的实际实现时模拟obj1.isValid() 方法

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:conf/test-context.xml"})
public class ServiceTest {

    @InjectMocks
    Service service;

    @Mock
    OBject1 obj1;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

    }


    @Test
    public void testValidate (){
        service.validate();
       //assert and other stuff
    }
}

此测试失败,当我调试验证方法时,我发现obj1 实例在Service 类中按预期注入,但obj2null 注入。因此测试失败... 有什么方法可以实现吗?

更新 当我读到一些 SO 答案时,我使用了 springockito。我将以下内容添加到测试类中,如下所示,但结果仍然相同:

@ReplaceWithMock
@Autowired  
Object2 obj2

【问题讨论】:

    标签: spring unit-testing mocking mockito spring-test


    【解决方案1】:

    您必须将@Autowired 注释添加到service 对象,以便service 中的所有其他属性正常注入,并为模拟类型注入模拟对象。

    在下面的示例中,Class2 的普通 bean 将被注入到 service 中,但 @InjectMocks 注释将注入 Class1 的模拟对象。

    服务

    @Component
    public class Service
    {
        @Autowired
        private Class1 class1;
    
        @Autowired
        private Class2 class2;
    
        public Class1 getClass1()
        {
            return class1;
        }
    
        public Class2 getClass2()
        {
            return class2;
        }
    }
    

    Class1

    @Component
    public class Class1
    {
        public String getName()
        {
            return "Class1";
        }
    }
    

    Class2

    @Component
    public class Class2
    {
        public String getName()
        {
            return "Class2";
        }
    
    }
    

    测试

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration({
        "classpath:application-context.xml"
    })
    public class ServiceTest
    {
        @Mock
        private final Class1 class1 = Mockito.mock(Class1.class);
    
        @InjectMocks
        @Autowired
        private Service service;
    
        @Before
        public void setup()
        {
            MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void test()
        {
            Mockito.when(class1.getName()).thenReturn("MockClass1");
            Assert.assertNotNull(service);
            Assert.assertEquals("MockClass1", service.getClass1().getName());
            Assert.assertNotNull("Class2", service.getClass2().getName());
        }
    }
    

    【讨论】:

      【解决方案2】:

      这可以通过@Spy实现

      您的代码应如下所示

      public class ServiceTest {
      
          @InjectMocks
          Service service;
      
          @Mock
          OBject1 obj1;
      
          @Spy 
          Object obj2 = new SomeObject("argument");
      
          @Before
          public void setUp() {
              MockitoAnnotations.initMocks(this);
          }
      }
      

      【讨论】:

      • 感谢您的回答,但我的 Object2 有其他自动装配的依赖项,我必须对其进行测试,所以这不适合我...
      【解决方案3】:

      实现此目的的另一种方法是使用 springocito。

      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(loader = SpringockitoContextLoader.class,locations={"classpath:conf/test-context.xml"})
      
      public class ServiceTest
      {
          @ReplaceWithMock
          @Autowired
          private Object1 object1
      
          @Autowired
          private Service service;
      
          @Before
          public void setup()
          {
             MockitoAnnotations.initMocks(this);
          }
      
         @Test
         public void test()
         {
         //assert stuff
         }
      }
      

      服务将被正确填充,除了将具有模拟实例的 Object1。将填充所有自动装配的内部 bean 的其余部分。

      【讨论】:

        【解决方案4】:

        不要使用 Autowired 和 InjectMocks。这是不好的做法。您可以同时使用@InjectMocks 和@Spy 来模拟真实对象并允许在此间谍对象内进行模拟

        【讨论】:

        • 当我在 object2 上使用 spy 时,它会模拟整个对象。但例如 obj2 有 dep1,dep2 有 2 个依赖项。我只想模拟 dep1。当我使用 Spy 时,它会模拟它们.在这种情况下,接受的答案有效。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-03
        • 2016-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多