嘲笑私人方法

时间:2018-02-07 05:04:51

标签: java junit mockito powermock easymock

我有一个私有的方法。现在,我不想在execute()方法上进行单元测试时调用此私有方法。我已经尝试过PowerMockito和所有这些,但是所有类型的模拟它仍然进入私有方法。

请建议使用可行的测试用例。会很感激。

@Component 
public class Employee implements SuperClass {

    @Autowired
    private FileTraverse fileTraverse;

    @Override 
    public void execute() throws Exception {
        List<String> traverse = fileTraverse.getFiles();
        Boolean t = isFileTraversed(traverse);
    } 

    private Boolean isFileTraversed(List<String> param1) {
        Boolean flag;
        //do some DB operation and return flag;
    }
}

3 个答案:

答案 0 :(得分:0)

@glytching是对的。它是在新服务/组件中提取方法并为其创建模拟的最佳变体。在这种情况下,您的代码是可测试的,您可以重复使用此组件...

但是,如果您只有一个用于此方法的用例,并且您不想仅为一个方法(辅助方法)创建服务/组件,则可以将方法可见性级别从私有更改为受保护或包默认。在这种情况下,您可以在子类中重写此方法以进行测试并使用此子类。你应该做什么: 为要测试的类创建子类,并使用此子类的实例而不是目标类。

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ServiceOverrideTestConfiguration.class)
public class MainServiceTest {
    @Autowired
    @Qualifier("subMainService") // or add @Primary and don't use Qualifier
    private MainService service;
    @Autowired
    private SecondService secondService;

    @Test
    public void test(){
        Object result = service.getResultFromMainService();
        --here, method getResultFromMainService call inside the overrided 
            method that we can change
        assertNotNull(result);
    }    
}

@ContextConfiguration
@Import(ApplicationConfigure.class)
class ServiceOverrideTestConfiguration {

    @Bean("subMainService")
    // or add @Primary and don't use Qualifier
    MainService mainServiceSubBean(){
        return new MainServiceUnderTest();
    }
}

class MainServiceUnderTest extends MainService{    
    @Override
    Object getResultFromMainServiceFromPrivate(){
        return "SOME DEFAULT";
    }    
}

_

#Parallel function
runnable_X<-function(ID) {
  require(R.utils)
  Sys.sleep(ID)
  return(ID)
}

!请注意,在极少数情况下,当您需要模拟/存根某些方法并且无法使用PowerMock或任何其他库时,请将此方法视为一种解决方法。更好,尝试重构并在代码中带来可测试性

答案 1 :(得分:0)

不要模仿私人方法。

请参阅以下建议:

SomeFunction

所以在isFileTraversed中 - 你将有一个数据库操作。此操作可能通过DAO / Repository对象执行。

所以你的代码可能会像:

@Component 
public class Employee implements SuperClass {

    @Autowired
    private FileTraverse fileTraverse;

    @Override 
    public void execute() throws Exception {
        List<String> traverse = fileTraverse.getFiles();
        Boolean t = isFileTraversed(traverse);
    } 

    private Boolean isFileTraversed(List<String> param1) {
        Boolean flag;
        //do some DB operation and return flag;
    }
}

您需要做的是模拟DatabaseAccessDao类上的公共checkFileTraversed()方法。

1)不要在字段上@Autowire - 更喜欢构造函数注入。

2)你确定要返回布尔值吗?允许“null”作为返回值吗?如果不是 - 考虑使用原始布尔类型;

答案 2 :(得分:0)

其他人都是对的。你应该尽量避免模仿私有方法。如果你真的需要模拟它,只需删除private以将其置于默认范围内。

BUT

为了完整起见,您确实可以使用PowerMock。以下是使用PowerMock和EasyMock的示例。

public class Employee {

  public void execute() {
    // If our mock is working, isFileTraversed will return false
    assertThat(isFileTraversed(Collections.emptyList())).isFalse();
  }

  private Boolean isFileTraversed(List<String> param1) {
    return true;
  }

}

@RunWith(PowerMockRunner.class)
@PrepareForTest(Employee.class)
public class EmployeeTest {

  @Test
  public void execute() throws Exception {
    Employee employee = PowerMock.createPartialMockForAllMethodsExcept(Employee.class, "execute");

    PowerMock.expectPrivate(employee, "isFileTraversed", Collections.emptyList()).andReturn(false);
    PowerMock.replay(employee);

    employee.execute();

    PowerMock.verify(employee);
  }

}