【问题标题】:Testing @Postconstruct with Mockito使用 Mockito 测试 @Postconstruct
【发布时间】:2018-09-25 16:25:39
【问题描述】:

为什么当我通过Mockito 注入模拟时我的@Postconstruckt 方法没有调用?

@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

【问题讨论】:

  • 你想从这个模拟中得到什么?您是在其他地方使用此服务还是在实际测试该服务?
  • 我只是想知道 mockito 如何对待@postconstruct。我期待类似的东西:CONSTRUCTOR,POST CONSTRUCT
  • 它为什么要这么做?您正在模拟(例如伪造)与该对象的 Spring 驱动交互,因此 @PostConstruct 的 Spring 构造甚至不适用。再说一次,你用这个模拟的目标是什么?您想测试此服务还是想在其他地方使用您的服务的模拟?

标签: java spring mocking mockito postconstruct


【解决方案1】:

因为 PostConstruct 只是弹簧概念。但是你可以手动调用 postConstruct。

@Before
public void prepare() {
    MockitoAnnotations.initMocks(this);
    this.service.init(); //your Injected bean
}

【讨论】:

  • @PostConstruct 不仅仅是一个 Spring 概念,它甚至不是一个 Spring 注解。
【解决方案2】:

我通过添加方法 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 - 这种组合可以让您在测试中获得常规服务

    @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 - 这种组合可以让您在测试中获得服务并使用 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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-24
      • 1970-01-01
      • 2017-03-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多