-1

We are migrating to JUnit5 and removing PowerMockito since Mockito now supports mockStatic. Before, PowerMockito offered Whitebox.setInternalState(..) making it possible to set values final fields (constants)
I have a class like

public class MyClass {
    
    private static final String myField = Props.getString("myField");
    
    public boolean myMethod() {
        //uses my field
    }
    
}

and my Test looks like this

class MyClassTest {

    @Test
    void myTest() {
        try (MockedStatic<Props> propsMockedStatic = Mockito.mock(Props.class)) {
            propsMockedStatic.when(() -> Props.getString("myField")).thenReturn("Hello!!");
            MyClass myClass = new MyClass();
            //more code
        }
    }
}

The problem is that when I introduce more tests I see that the myField gets mocked only once when I run the Tests although I use a new instance every time. This results in braking tests since on other cases I want myField to have different values but when I run them separately everything completes successfully

  • You might want to check other questions like https://stackoverflow.com/questions/26234742/resetting-static-fields-for-junit-tests – Progman Jun 14 '22 at 12:52
  • 2
    Non-Answer: consider changing your production code. Do not try to use mocking frameworks with static methods or fields. The static stuff just makes your code 10 times **harder to test**, for unit tests, but also for any other sort of test you might want to do. Seriously: instead of learning how to use Mockito for static stuff, rather ask yourself how you can improve your production code to be **easy to test**, so that you avoid the whole static-mocking stuff completely. (I have been there with powermock(ito), and rest assured: it is a world of pain. Do not enter) – GhostCat Jun 14 '22 at 12:56
  • In our case: instead of pulling the actual property value, why not make the **key** `myField` your constant, and then any code that needs the property value, just reads it from that Props object? When it is not a real compile time **constant**, why do you force yourself to treat it like one? – GhostCat Jun 14 '22 at 13:05
  • 1
    "Constant field gets initialized only once under Junit5" and more generally in Java. This is how static initialization works. – Andy Turner Jun 14 '22 at 13:08
  • @AndyTurner ofc I understand why this happens. Previously we were using PowerMockito which offerer Whitebox making it easy to mock such final fields by using Whitebox.setInternalState(..). What I want to do is a walkaround so this can work in JUnit5 and mockito 4.6. Thanks for the answers but the production code cannot be changed just for a unit test to work. – Marko Gila Jun 15 '22 at 09:01
  • The point is to change the production code to make the unit test to work. The point is to improve your production code so that it becomes easier to test and doesn't need expensive band aids every time some other code needs to deal with it. – GhostCat Jun 15 '22 at 09:13
  • 1
    And note: Whitebox was always in the org.mockito.**internal** ... that is what I am talking about: at some point, you wrote hard to test code. You worked around by using a feature that said right in its name "maybe better not use me". And now you are in trouble. Of course, you can continue to go down this route, and put band aids on the symptoms. Paying the price every time you do so. – GhostCat Jun 15 '22 at 09:17
  • Ok, thanks for the answers, I get your point, but I thought of asking if someone has dealt with something similar and achieved to do that without modifying the production code of a legacy project. – Marko Gila Jun 15 '22 at 09:36
  • Also, is it a bad practice to have a constant filled like this? I think that's what we want to achieve. After all it's just a string – Marko Gila Jun 15 '22 at 09:58
  • Think about it: you made something a constant ... but you have the urgent need to change its value during the life time of the corresponding class. As said before: if your code does different things based on the content of that field, then the inability to change that value hampers more than just the unit tests. – GhostCat Jun 15 '22 at 14:19
  • _ without modifying the production code of a legacy project._ - test classes are not production code. – Thorbjørn Ravn Andersen Jun 23 '22 at 12:44

1 Answers1

-2

A temporary workaround that I found on a Stack overflow post is this one https://stackoverflow.com/a/56043252/17984773. It works with JDK17, Junit5, and Mockito 4.6. Answering that here in case someone searches for the same issue, for me it took a lot of time to bump into this answer. It may be temporary but for now it works