0

Basically I want to run the test on a clean slate, so I don't want @PostConstruct populating the data field.

I have a private static variable in service class that gets data loaded from the repository upon build success. Is there a way to run unit tests without this data? (with fresh classes)

In the test I'm mocking a repository's getData function but there is an if empty statement in there. Since on build, the static variable is populated the tests won't use the mocked function, so the test fails.

What I found works is to call an empty variable function of the service within a @Before annotation. But this is not a stable solution.

sample of code:

private static List<Data> data = Collections.synchronizedList(new ArrayList<Data>());

@PostConstruct
private List<Data> populateData() {

  data = repo.findData();

  return data;
}

public List<Data> getData() {

  if (data.size() == 0) {
    populateData();
  }
  return data;
}

test:

@Mock
private Repository repo;

@Mock
private static Data data;

@InjectMocks
private Service service;

private List<Data> rows = new ArrayList<Data>();

@Before
public void mockMethodSetup() {

  //service.evictData();

  data.setValue(1);

  when(repo.findData()).thenReturn(data);

}

@Test
public void shouldReturnDataResponse() {
  List<Data> dataReturned= service.getData();
  assertEquals("Response was not equal to the mock.", dataReturned, data);
}
Raket Makhim
  • 147
  • 1
  • 2
  • 9

1 Answers1

1

As far as I understand you try to replace the static data field with something different in your test.

You can do that using Reflections: link.


This may or may not work, depending on whether your repo.findData() call works or produces an exception. I suggest that you do not bring in any know-how to the UnitTest regarding the @PostConstruct annotation, so that the method will not be executed.


Also if you define @Mock for data you'll need to define behaviour for it.
Note that data should not be a static field in your test.

Ps.: @InjectMocks doesn't have any effect on static fields.

second
  • 4,069
  • 2
  • 9
  • 24
  • Basically I want to run the test on a clean slate, so I don't want ````@PostConstruct```` populating the data field. Does the change Reflections make stay with the service class? – Raket Makhim Nov 19 '19 at 15:24
  • What `Runner` do you use that invokes `@PostConstruct`? If you use reflecftions after the initialisiation has taken place it will override it, however if another instance of the object is created it might override it again. – second Nov 19 '19 at 15:26
  • I'm using MockitoJunitRunner which works locally but fails on CI GitLab because it has to build (and so @PostConstruct) and therefore the data is populated before the tests. Therefore the ````if```` in Service.getData() wont allow me to populate it. – Raket Makhim Nov 19 '19 at 15:31
  • `MockitoJunitRunner` has no concept of `@PostConstruct`. If the method is invoked it must come from somewhere else. Check your `CI GitLab` configuration. – second Nov 19 '19 at 15:34
  • GitLab CI pipeline builds before it runs unit tests – Raket Makhim Nov 19 '19 at 15:35
  • 1
    This turned into a configuration issue. Trying asking another question for this, I can't answer that. – second Nov 19 '19 at 15:37