0

I have a spring project, which contains a class called EnvUtils:

package com.example;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Objects;

@Component
public class EnvUtils {

    @Value("${env}")
    private String env;

    /**
     * Develop environment
     */
    public boolean isDev() {
        return Objects.equals(env, "dev");
    }

    /**
     * Production environment
     */
    public boolean isProd() {
        return Objects.equals(env, "prod");
    }

}

I wrote a simple test, which set env's value to dev, and checked the result of isDev():

package com.example;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.util.ReflectionTestUtils;

@SpringBootTest
@ExtendWith(MockitoExtension.class)
class MainControllerTests {

    @MockBean
    private EnvUtils envUtils;

    @Test
    void fieldTest() {
        ReflectionTestUtils.setField(envUtils, "env", "dev");
        Assertions.assertTrue(envUtils.isDev());
    }

}

The test should pass because the value of env is dev, which means envUtils.isDev() should definitely return true. However, this test failed. I debugged it and found that envUtils.env was dev, as expected, but envUtils.isDev() returned false. How could it be? Have I done something wrong?

Searene
  • 25,920
  • 39
  • 129
  • 186
  • How did this test fail? What is your actual test? There is no point to test `ReflectionUtils.setField()`. Also you have `MockitoExtension` but you are using `@MockBean`? Should this even be a `@SpringBootTest`? – pirho Feb 09 '21 at 18:03

2 Answers2

2

You are mocking EnvUtils class, so the method isDev is mocked also, the real method of the class will not be invoked.

In your case, you don't need @MockBean, remove it. And don't forget to initialize the envUrils object using default constructor.

@SpringBootTest
@ExtendWith(MockitoExtension.class)
class MainControllerTests {

    private EnvUtils envUtils = new EnvUtils();

    @Test
    void fieldTest() {
        ReflectionTestUtils.setField(envUtils, "env", "dev");
        Assertions.assertTrue(envUtils.isDev());
    }

}
Ismail
  • 2,322
  • 1
  • 12
  • 26
0

You mocked whole EnvUtils class. If you change it to Spy it would be work. Read this:mock vs spy

Try this:

@ExtendWith(MockitoExtension.class)
class MainControllerTests {

    @SpyBean
    private EnvUtils envUtils;

    @Test
    void fieldTest() {
        ReflectionTestUtils.setField(envUtils, "env", "dev");
        Assertions.assertTrue(envUtils.isDev());
    }

}
tomeszmh
  • 218
  • 2
  • 9