模拟非静态的对象方法,它不是在测试方法中创建的

时间:2015-01-13 07:36:11

标签: java unit-testing mocking

在这种情况下是否可以使用Mockito,PowerMock或任何其他模拟对象生成器模拟RentalProfile.getStartDate()?

我尝试做的有点像这样,但它不起作用:

@Test
public void testsetAmortizationModel() throws Exception {
    // ...
    RentalProfile mock = Mockito.mock(RentalProfile.class);
    Mockito.when(mock.getStartDate()).thenAnswer(new Answer<String>() {
        @Override
        public String answer(InvocationOnMock invocation) throws Throwable {
            return "2014-12-21";
        }
    });
    Mockito.verify(mock);
    // ...

}

还有调用RentalProfile.getStartDate()的方法。它没有返回&#34; 2014-12-21&#34;:

public void classMethod() {
    List<RentalProfile> tPaymentPlans =
    aCompositeAgreement.getRentalProfiles().getRentalProfile();
// ...
    for (RentalProfile tRentalProfile : tPaymentPlans) {
        LocalDate tStartDate = BridgeDateUtils.stringWithHyphenToDate(
            tRentalProfile.getStartDate()); // tRentalProfile is RentalProfile object
// ...
}

3 个答案:

答案 0 :(得分:0)

您发布的代码存在一些问题:

  1. 正如Vincent建议的那样,您可以将Mockito.when(...).thenAnswer(...)替换为when(mock.getStartDate()).thenReturn("2014-12-21")

  2. 来简化模拟操作 此处不需要
  3. Mockito.verify(mock);,因为它通常用于检查是否已在模拟上调用特定方法(带有预期参数)。

  4. 您无法在您的类实例中注入模拟以便于测试。

  5. 以下示例类将正确运行并为您的测试注入依赖项:

    public class MyClass {
    
       private RentalProfile tRentalProfile = null;
    
       public MyClass(RentalProfile tRentalProfile) {
          this.tRentalProfile = tRentalProfile;
       }
    
      public void classMethod() {
        // ...
        LocalDate tStartDate = BridgeDateUtils.stringWithHyphenToDate(
          tRentalProfile.getStartDate()); // tRentalProfile is RentalProfile object injected to MyClass
        // ...
      }
    
    }
    

    现在可以通过以下方式用Mockito嘲笑:

    @Test
    public void testsetAmortizationModel() throws Exception {
        // ...
        RentalProfile mock = Mockito.mock(RentalProfile.class);
        Mockito.when(mock.getStartDate()).thenReturn("2014-12-21");
    
        MyClass myClass = new MyClass(mock);
        myClass.classMethod();
    
        // Here you verify whether method has been successfully executed 
        // i.e. verify return value, other class parameters,, mock method calls etc.
    
    }
    

答案 1 :(得分:0)

问题是没有使用测试中创建的模拟实例。

@Test
public void testsetAmortizationModel() throws Exception {
    // ...
    RentalProfile mock = Mockito.mock(RentalProfile.class);
    when(mock.getStartDate()).thenReturn("2014-12-21");
    Mockito.verify(mock);
    // ...

    MyClass classToTest = new MyClass(mock);
    classToTest.myMethod();
}

你的班级:

public class MyClass {
    private RentalProfile profile;

    public MyClass(RentalProfile profile) { this.profile = profile; }

    public void myMethod() {
        for (RentalProfile tRentalProfile : tPaymentPlans) {
            LocalDate tStartDate = BridgeDateUtils.stringWithHyphenToDate(
                this.profile.getStartDate());
        }
    }
}

您必须解耦变量的创建。您真正想要测试的不是RentalProfile的创建,如果它返回此值,您的方法会做出反应。

在我的例子中,我选择通过构造函数注入配置文件。

看看这个问题:https://stackoverflow.com/a/25135757/2015239 这是完全相同的问题:你必须解耦代码。

答案 2 :(得分:0)

您可以使用JMockit库模拟在测试代码中创建的对象,如下所示:

@Test
public void testSetAmortizationModel(@Mocked final RentalProfile mock)
{
    new Expectations() {{ mock.getStartDate(); result = "2014-12-21"; }};

    // No need to pass "mock" into the SUT here; any future instance will be mocked.
    MyClass classToTest = new MyClass();
    classToTest.myMethod();
}