使用Mockito测试@PostConstruct

9
为什么当我通过 Mockito 注入模拟对象时,我的 @PostConstruct 方法没有被调用?
@Service
public class MyService {
    public MyService() {
        System.out.println("CONSTRUKTOR");
    }

    @PostConstruct
    public void init() {
        System.out.println("POST CONSTRUCT");
    }

@RunWith(MockitoJUnitRunner.class)
public class Mockito1 {

    @InjectMocks
    private MyService service;

    @Before
    public void init() {
    }

输出: 仅限:CONSTRUKTOR

你希望从这个模拟中获得什么?你是在其他地方使用此服务还是正在测试该服务? - Makoto
我只是在想Mockito如何处理@PostConstruct。我期望得到类似的结果:构造函数,后置构造函数。 - Jan Testowy
1
它为什么要与那个做任何事情?你正在模拟 Spring 驱动的对象交互,因此 Spring 的 @PostConstruct 构造甚至不适用。那么,你使用这个模拟的目的是什么?你想测试这个服务还是想在其他地方使用你的服务模拟? - Makoto
3个回答

5
由于PostConstruct只是Spring的概念,但您可以手动调用postConstruct。
@Before
public void prepare() {
    MockitoAnnotations.initMocks(this);
    this.service.init(); //your Injected bean
}

25
@PostConstruct 不仅是 Spring 的概念,它甚至不是 Spring 的注解。 - M. Deinum

4
我稍微修改了您的服务,添加了一个名为foo的方法:
@Service
public class MyService {
    public MyService() {
        System.out.println("CONSTRUKTOR");
    }

    @PostConstruct
    public void init() {
        System.out.println("POST CONSTRUCT");
    }

    public String foo() {
        return "bar";
    }
}

如果您想获得所描述的行为,至少有两种可能性:

  1. @RunWith(SpringJUnit4ClassRunner.class) + @Autowired - that combination will let you to get a usual service in your test

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = MyService.class)
    public class Mockito1 {
    
        @Autowired
        private MyService service;
    
        @Before
        public void init() {
        }
    
        @Test
        public void name() throws Exception {
            System.out.println(service.foo());
        }
    }
    
这段代码将会输出:
CONSTRUKTOR
POST CONSTRUCT
bar
  1. @RunWith(SpringJUnit4ClassRunner.class) + @SpyBean - that combination will let you to get a service in your test and to modify it's behaviour using Mockito

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = MyService.class)
    public class Mockito1 {
    
        @SpyBean
        private MyService service;
    
        @Before
        public void init() {
        }
    
        @Test
        public void name() throws Exception {
            System.out.println(service.foo());
            Mockito.when(service.foo()).thenReturn("FOO");
            System.out.println(service.foo());
        }
    }
    
这段代码将会输出:
CONSTRUKTOR
POST CONSTRUCT
bar
FOO

0

@PostConstruct 是由 JSR 250 定义的注释,在您当前的测试中将被忽略,因为您正在使用 @RunWith(MockitoJUnitRunner.class),即一个不知道此注释的 JUnit 运行器。如果您正在编写单元测试,它们应该是简单的,并且只测试应用程序的业务逻辑,但如果您想编写使用某些能够处理此类注释的第三方代码(例如 Spring)的集成测试,则可以使用以下注释对测试类进行注释:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppConfig.class})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接