2

I have class:

@Service
public class A {

  @Value("${a.b.c}")
  private String abc;

  public void foo() {
   sout(abc);
  }
}

I Have test class:

@SpringBootTest
@SpringBootConfiguration
@RunWith(SpringRunner.class)
@TestPropertySource(locations = "classpath:application.yml")
public class TestA {

  @Value("${a.b.c}")
  private String abc;

  @InjectMocks
  private A a;

  @Test
  public void testFoo() {
    this.a.foo();
  }
}

When I debugging the test method testFoo(), I see that variable abc is read from the application.yml file. But, inside the foo() method, I see that the variable abc is null. How can I set variable abc such that it is available in method foo() when I trying to test this method?

5
  • Like that: @SpringBootTest({"a.b.c=myValue"}) Commented Nov 27, 2018 at 18:59
  • I tried. Still null Commented Nov 27, 2018 at 19:09
  • @AntonKolosok try to replace @InjectMocks annotation in the class TestA to the @Autowired Commented Nov 27, 2018 at 19:13
  • Possible duplicate of How do I mock an autowired @Value field in Spring with Mockito? Commented Nov 27, 2018 at 19:14
  • A better solution is to use constructor injection, which will usually let you avoid involving Spring at all and simply do new A(myTestAbc). Commented Nov 27, 2018 at 19:32

2 Answers 2

4

Step one is to answer this question: Am I unit testing the code in my class or am I integration testing the combination of Spring and some collection of code that includes my class?

If you are unit testing your code, then it is not necessary to have Spring do its thing. Instead, you only need to instantiate your class, set the values that Spring would have set for you, execute the method you are testing, then verify that your method executed correctly.

Here is your example unit test rewritten as I suggested:

public class TestA
{
  private static final String VALUE_ABC = "VALUE_ABC";

  private A classToTest;

  @Test
  public void testFoo()
  {
    classToTest.foo();
  }

  @Before
  public void preTestSetup()
  {
    classToTest = new A();

    ReflectionTestUtils.setField(
      classToTest,
      "abc",
      VALUE_ABC)
  }
}

Some Notes:

  1. ReflectionTestUtils is part of Spring-test.
  2. You don't need to use @InjectMocks because you have no mocks to inject.
  3. I don't know what sout is, so I excluded it from the test. You should verify that the sout method was called with the correct value (in this case VALUE_ABC).
  4. If you are just unit testing your code, you don't need Spring, which means that you don't need to use the @RunWith annotation.
Sign up to request clarification or add additional context in comments.

1 Comment

Im REALY, REALY thank you. I spend a lot of time to beat it by myself.
0

You can try to overide the properties like that:

@TestPropertySource(locations = "location.properties",
  properties = "a.b.c=123")

Example taken from here

1 Comment

Still have null in foo() method

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.