-1

I know that it's quite hard to test many features of Java language. For example, it would be impossible to test a private variables of a class or similar methods. I generally tackle this by making a nested class, where this nested class is a unit test, such that :

public class MyClass{

 private String somePrivate;
  // omitted for brevity


  @RunWith(MockitoJUnitRunner.class)
  public static class MyClassUnitTest{
     @InjectMockito
      MyClass myclassMocked;

// so forth...
  }

} 

thus no need for reflection/powermock or others!

This structure helps me to test all unreachable members or methods of a class. But it appears that i also should make an automated build where maven will look up this nested classes for unit tests and run it when i mvn clean test in the deployment.

I've been trying to find any answer on this but to no avail i couldn't find any spec of maven or maven-surefire-plugin to say that 'hey please look at these nested classes in the src/main folder and mark them as unit test'. Also, i am using springboot to package all of my project (thus most of the dependencies are with spring)

Anyone up for solution?

tepetrol
  • 94
  • 8
  • 1
    "For example, it would be impossible to test a private variables of a class or similar methods" - yes, and completely unnecessary. Also, mixing your unit tests into your production code? That is wrong on so many levels... – Smutje Jan 28 '20 at 15:01
  • terrible idea, private methods are tested in an indirect manner by observing their effect. – Andrei Dragotoniu Jan 28 '20 at 15:49
  • I disagree. Some examples: - You can have a private methods and based on some other services, you consume something in that private methods and you want to know the result - a default package methods, which means you can't import to src/test folder Mixing? it's called nested (static) class. Nested classes increases encapsulation for the unit test. And you don't have a clear reason why this wrong (please provide so). – tepetrol Jan 28 '20 at 15:55
  • A unit test should simply be located in `src/test/java` and never in `src/main/java` that's the way it is. Everything which is in `src/main/` will be part of the production code which is being packaged into the resulting jar/war etc. If this will contain testing code that's simply wrong. – khmarbaise Jan 28 '20 at 17:09
  • Having code based on your example in production code means also you have to have dependencies like JUnit and mockito in production code which means this jar's will be part of the resulting packaging which is also wrong. In general if you need to test private methods this means you are doing too much within a single class (Single Responsible Principle). This means you need to refactor your code.... – khmarbaise Jan 28 '20 at 17:10
  • Ok. So far @khmarbaise provided good reason for packaging-related: it's much more lightweight and clearly defined. And Maven has a more strict build categories between `main` and `test`. However, Java still allows you to do this if didn't want to use maven as your build tool and if you did, i still find no reason to reject this entirely (core java answer if any please?). – tepetrol Jan 29 '20 at 07:16
  • Of course you can do that if you like but that's against all best practice to have test code in your production code plus dependencies etc. Apart from that. This will work up to JDK8 but if you like to go the modules in JDK9+ this will not work anymore based on split packages (and that's real hard reason). If you continue to use that approach you will never be able to migrate to JDK9+. You can do in Java general many things like static variables/static initializers but best practice is to avoid that for good reasons. – khmarbaise Jan 29 '20 at 07:23
  • Last but not least you should think about the maintenance of such kind of code. This will cause many issues in the future and will reduce your own development speed and more than that others who need to maintain this code later if you are not available anymore (maybe change the company etc.) and that is a kind of responsibility you have as a developer which you seemed to be not aware of cause you seemed to ignore all best practices available. I've seen several codebases which such obscurities which always produces issues. Code is not written for a machine it's written for humans. – khmarbaise Jan 29 '20 at 07:31

1 Answers1

2

For example, it would be impossible to test a private variables of a class or similar methods

You don't need to do this - private methods are private, and they are indirectly tested by testing methods that use them.

You should not be embedding test code or libs such that they have to ship with production software, period.

Don't do what you are proposing.

Edit based on your comment:

As for how you would do it technically, Maven only supports 1 directory for test sources.

You could do something like create an integration test setup that would find the tests in your src/main directory, but the reason this is not easy to do with Maven is because Maven promotes sane patterns and your pattern is not one of those.

Howto add another test source folder to Maven and compile it to a separate folder?

mikeb
  • 10,578
  • 7
  • 62
  • 120
  • Unfortunately this is not an answer but rather an advise. Would be great if you can extend your answers technically speaking... – tepetrol Jan 28 '20 at 16:26
  • See my edits - technically speaking Maven does not support > 1 test directory - https://stackoverflow.com/questions/10138559/howto-add-another-test-source-folder-to-maven-and-compile-it-to-a-separate-folde/40917384 – mikeb Jan 28 '20 at 16:41
  • @tepetrol It is an answer with reason why you should not do that... – khmarbaise Jan 28 '20 at 17:12
  • @mikeb This is simply wrong cause you can define more than one test directory. It's best practice not to do so. Apart from that JDK9+ with modules it is limited also by JDK itself... – khmarbaise Jan 29 '20 at 07:33