希望 spring bean 具有模拟和真实实现+spring+mockito

Want spring bean to have mocked as well as real implementations+spring+mockito

我有一个 class Service 想要测试。基本上,我遇到了一个问题,因为我希望 Service 对象被部分模拟。只有 obj1 应该被嘲笑,其他合作者应该是真实的。我的代码类似于:

@Component
public class Service {

    @Autowired
    Object1 obj1;

    @Autowired
    Object2 obj2;

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

    }
}

现在在测试上述 Service class 的验证方法时,我想在调用 obj2[=25= 的实际实现时模拟 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 class 中预期的模拟,但是 obj2 被注入了作为 null。因此测试失败... 有什么办法可以做到这一点吗?

更新 当我阅读一些 SO 答案时,我使用了 springockito。我将下面的东西添加到测试 class 中,如下所示,但结果仍然相同:

@ReplaceWithMock
@Autowired  
Object2 obj2

这可以通过 @Spy

实现

您的代码应如下所示

public class ServiceTest {

    @InjectMocks
    Service service;

    @Mock
    OBject1 obj1;

    @Spy 
    Object obj2 = new SomeObject("argument");

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

您必须将 @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());
    }
}

实现此目的的另一种方法是使用 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
   }
}

服务将得到正确填充,但对象 1 除外,它将模拟 instance.Rest 所有自动装配的内部 bean。

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