0

I am testing a Cordova plugin in Java/Android and I need to initialize my Plugin class and set some state before I run my Tests.

  @Before
  public void beforeEach() throws Exception {
    System.out.println("Creating new Instance ");

    PowerMockito.mockStatic(Helpers.class);
    PowerMockito.when(Helpers.canUseStorage(any(), any())).thenReturn(true);

    MyLogger myLoggerMock = PowerMockito.mock(MyLogger.class);
    PowerMockito.doNothing().when(myLoggerMock, "log", anyString());

    PowerMockito.whenNew(MyLogger.class).withAnyArguments().thenReturn(myLoggerMock);

    this.sut = spy(new FilePicker());
    PowerMockito.doNothing().when(this.sut).pick(any(), any());
  }

I want to create a Test Suite / Java Class per public function, but I do not want to repeat that code every time.

Is there a way to share that before each between test suites? I have found ClassRule but I think I do not do what I need (or I am understanding it wrong... I am really new in Java)

In Typescript we can share beforeEachfunctions with several suites, and each suite can have their own beforeEach

distante
  • 6,438
  • 6
  • 48
  • 90

1 Answers1

2

One possible ways is using inheritance:

Make all test classes extend from one "parent test" class and define a @Before in a parent class. So it will be called automatically for all the subclasses:

     public class ParentTest {

         @Before
         public void doInitialization() {
          ....
         }
     }

     public class Test1Class extends ParentClass {

         @Test
         public void fooTest() {
          // doInitialization will be executed before this method
         }

         @Test  
         public void barTest() {
           // doInitialization will be executed before this method as well
         }
     }

Two notes:

Note 1

In the code you use sut (subject under test) - this obviously should not be in the parent's doInitialization method, so its possible that Test1Class will also have methods annotated with @Before (read here for information about ordering and so forth) Then the `sut gets initialized with Spy which is frankly weird IMHO, the Subject Under Test should be a real class that you wrote, but that's beyond the scope of the question, just mentioning it because it can point on mistake.

Note 2

I'm writing it in an an attempt to help because you've said that you're new in Java, this is not strictly related to your question...

While this approach works in general you should be really cautious with PowerMockito. I'm not a PowerMockito expert and try to avoid this type of mocks in my code but in a nutshell the way it manipulates the byte code can clash with other tools. From your code: you can refactor the HelperUtils to be non-static and thus avoid PowerMocking in favor of regular mocking which is faster and much more safe. As for the Logging - usually you can compromise on it in unit test, if you're using slf4j library you can config it to use "no-op" log for tests, like sending all the logging messages into "nothing", and not-seeing them in the console.

Smile
  • 3,832
  • 3
  • 25
  • 39
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
  • Thanks for your comments they really help me! I kind of know the test looks (and is) weird. The thing with the Helpers is that I can not really injecting it into my class. The framework (Cordova) creates the new instance and I can not inject any dependency there. Also I am spying in my `sut` because in there I just want to test one function `execute` and I didn't wanted to add the mocks needed for the `pick` function so I wanted to prevent the test to call it. I Haven't found other way to do this. Maybe this is the reason why I haven't found any Android Cordova Plugins with unit tests... – distante Nov 01 '19 at 06:17