Java Unit Test: Replace a private method under test

被刻印的时光 ゝ 提交于 2019-12-04 12:32:06

You certainly can solve this situation with JMockit. One way would be to define a "mock-up" class, for example:

public class MyTest
{
    @Test
    public void testDoSomething()
    {
        new MockUp<ClassWhichDependsOnOtherBundles>()
        {
            @Mock
            void secondThing()
            {
               // do anything here
            }
        };

        new ClassWhichDependsOnOtherBundles().doSomething();
    }
}

Only the secondThing() method in the mocked class will be replaced by JMockit. The JMockit Expectations API could also be used, with partial mocking.

You are coupling your implementation to the creation of the osgi object (doing it inside secondThing() or the class itself). If you passed the implementation into your class from the outside, you could use a stub/mock when testing instead.

I also think dependency injection would solve this problem. If you don't want another framework in your project and this is the only place which makes trouble, you could define an interface for secondThing and have 2 implementations for that, one for the original code and an empty one for the unittest.

My advice - redesign your application. If you want to change the behaviour of a private method:

  • make it protected / public and override it in a mock-like object
  • move the functionality out of the method into a helper class, which is injectable (via dependency injection). Then mock that helper an inject the mock into the class-under-test, instead of the original heloper.

A workaround may be some byte-code manipulation technique, but I don't recommend such.

there is a nice stub-pattern

ProductionClass.java:


public class ProductionClass {
  ...
  //default visibility to make it available for stubbing
  void firstThing(){...}

  ...
}

BlaTest.java (same package as production class):


public class BlaTest {

 @Test
 void test_xx(){
   //use stubbed impl
   ProductionClass sut = new ProductionClassStubbed();
   sut.doSomething();
 }
}

class ProductionClassStubbed extends ProductionClass{

 @Override
 void firstThing(){
   //stub out fill in what you want (like dummy behaviour)
 } 
}

One different thing. I saw a final modifier in your sample-code. Beware of using final modifier. They are evil for testability. Only use if really really necessary.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!