简体   繁体   中英

How to write unit tests for method which calls other methods?

This is a really bad sample of code. Sorry about that. I want to write a unit test for myMethod(). This only calls other methods and return String str1. I don't see there is any need of testing this code.

public class MyClass{
    private String str1;
    private String str2;

    private void m1(){..}
    private String m2(){  
         // do something
        return someString;

    }
    public String myMethod(String s1){
      str2 = s1;
      m1();
      str1 = m2();
      return str1;
    }
}

There are various ways to write unit tests.

A) You observe behavior. You create an object of your class under test, then you call methods; and then you assertThat on the values that are returned.

B) When your object uses other objects, then you might have to turn to mocking frameworks, for example to verify that you see the expected method calls on those objects.

In your case, it really depends on what m1/m2 are doing. As said - the best unit tests are those that only check the "observable" behavior of your code under test. Like those examples:

@Test(expected=NullPointerException.class)
public void testMyMethodWithNull() {
  new MyClass().myMethod(null);
}

The above would check that when calling your method with null ... a NPE is thrown.

@Test
public void testMyMethodWithEmptyString() {
  MyClass underTest = new MyClass();
  assertThat(underTest.myMethod(""), is("some expected string for empty input"));
}

That one does some different checking for EMPTY input.

And so you work your way through all inputs that make sense. Of course, the idea here is that all possible behavior of your class under test can be checked this way. If there are others that come into play, you have to take them into consideration of course. But ideally, that should not be the case: you should design all your code so that it can be fully tested as easily as possible; and ideally without the need to write anything else but such kind of tests.

I completely agree with GhostCat :

[…] the best unit tests are those that only check the "observable" behavior of your code under test.

Therefore, only test the public contract of your class under test (CUT).

However, there're rare situations in which you may need to test private methods, eg if you're working with legacy code. One way to do this is with PowerMockito :

PowerMockito.verifyPrivate(cut).invoke("m1");

Where cut is an instance of your CUT – MyClass .

Checkout these questions for further opinions and references:

"I don't see there is any need of testing this [private method]."

Yes. That's right.

A method that is private doesn't need any direct testing. Of course, private methods should be covered , but since they are private and NOT a part of your exposed API, they don't need to be tested as directly as public methods.

This book-- JUnit in Action: Second Edition --outlines many strategies for using JUnit effectively. Implementing TDD is one way to make sure that your class's non-public functionality is well-covered by your tests. That is, you write your unit tests first , then you implement your class to pass those tests. In this way, you only write functionality that you need, as defined by your tests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM