当前位置: 首页 > 知识库问答 >
问题:

模拟类嵌套在类中进行测试

史弘博
2023-03-14

Alpha-父级,子级为beta

public class Alpha {
  Beta beta;

  public Alpha(int argument) {}

  void start() {
    beta = createBeta();
  }

  Beta createBeta() {
    return new Beta(this);
  }
}

贝塔-阿尔法的孩子,查理

public class Beta {
  Alpha alpha;
  Charlie charlie;

  public Beta(Alpha alpha) {
    this.alpha = alpha;
    this.charlie = createCharlie();
  }

  Charlie createCharlie() {
    return new Charlie().shuffle();
  }
}

Charlie-有一个列表,通常在制作中会被洗牌

public class Charlie {
  List<Integer> list = new ArrayList<Integer>();

  public Charlie() {
    for (int i = 0; i < 6; i++) {
      list.add(i);
    }
  }

  public Charlie shuffle() {
    Collections.shuffle(list);
    return this;
  }

  @Override
  public String toString() {
    return list.toString();
  }
}

AlphaTest[需要此测试的帮助]-想尝试不同的洗牌变体,看看alpha/beta会如何反应。

public class AlphaTest {

  Charlie special = new Charlie();

  @Test
  public void testSpecialCharlie() {
    Alpha alpha = Mockito.spy(new Alpha(0));
    Beta beta = Mockito.spy(alpha.createBeta());

    Mockito.when(alpha.createBeta()).thenReturn(beta);
    Mockito.when(beta.createCharlie()).thenReturn(special);

    alpha.start();

    // FAILURE: expected:<[0, 1, 2, 3, 4, 5]> but was:<[0, 4, 1, 5, 3, 2]>
    assertEquals(special.list, alpha.beta.charlie.list);
  }
}

目标是用不同的组合测试Alpha/Beta。不知道最好的方法是什么?这正是复制的代码。也可以更改设置以方便测试。尝试了不同的变体,但没有任何效果。非常感谢您的帮助。

我不确定,我尝试了一堆方法(mocking outcreateCharlie()函数,mocking outCharlie类,mocking outschffle(),将createCharlie()移动到父Alpha类,没有什么真正正常工作,或者也许我错过了什么。任何帮助都将不胜感激。谢谢!

不知道为什么我不能这么做:

Charlie charlie = Mockito.mock(Charlie.class);
Mockito.when(charlie.shuffle()).thenReturn(special);

共有2个答案

张照
2023-03-14

多亏了达里奥的回答,我把贝塔班改成了

public class Beta {
  Alpha alpha;
  Charlie _charlie;

  public Beta(Alpha alpha) {
    this.alpha = alpha;
    this._charlie = getCharlie();
    // PROBLEM: If I use this._charlie here, that will use the wrong charlie!
  }

  Charlie getCharlie() {
    if (_charlie == null) {
      _charlie = new Charlie().shuffle();
    }
    return _charlie;
  }
}

然后,我从不使用alpha.beta._charlie访问查理,总是使用getCharlie(),这应该可以解决我的问题。谢谢你达里奥,非常感谢!

艾自强
2023-03-14

如果有人觉得这个有用,我会在下面留下我的初步答案。

首先,在构造函数的最后一行中放入Beta

System.out.println("Charlie created: " + this.charlie.hashCode());

运行测试后,你会看到查理被多次创建。

首先,当这被称为测试:

Beta beta = Mockito.spy(alpha.createBeta());

后来,当这被称为:

Mockito.when(alpha.createBeta()).thenReturn(beta);

所以Beta一直引用真实的Charlie,因为你嘲笑了createCharlie(),当你调用你的代码时:

Assert.assertEquals(special.list, alpha.beta.charlie.list);

真正的查理是被调用的,而不是被嘲笑的。你实现类的方式不是很好,但是如果我只是回答你应该在测试中改变什么——你应该称之为:

Assert.assertEquals(special.list, alpha.beta.createCharlie().list);

在这种情况下,将调用mockedCharlie,测试将通过。

先前的答复:

通常,当您进行单元测试时,您的重点是单个测试类。您可以使用@Spy/@InjectMocks。当你将测试Beta时,你应该嘲笑Charlie,当你将测试Alpha时,你会嘲笑Beta...

我不知道它的用途,但奇怪的是,createCharlie()randomize()返回Charlie的实例。无论如何,您可以通过getter懒洋洋地创建Charlie,如下所示:

public class Beta {
    private Charlie charlie;

    public Beta() {
    }

    public Charlie getCharlie() {
        if (charlie == null) {
            charlie = new Charlie();
        }
        return charlie;
    }

    public void doSomethingWithCharlie() {
        getCharlie().randomize();
    }
}

您可以像这样在测试中注入charlie:

public class BetaTest{
    @Mock(name="charlie") // variable name in Beta
    private Charlie charlieMock;

    @InjectMocks
    private Beta beta;

    @BeforeMethod
    public void before() {
        MockitoAnnotations.initMocks(this);
    }

    public void test1(){
        beta.doSomethingWithCharlie();
    }
}

另请参见@InjectMocks文档。

或者,您可以将包protected/Public方法添加到Alpha

Beta createBeta() {
    return new Beta(); 
}

或者

Beta getBeta() {
    if(beta==null){
        beta = new Beta();
    }

    return beta;
}

然后您可以注入到AlpharealBeta中,返回mockedCharlie

公共类字母测试{@Mock charlieMock;

@Spy
Beta beta;

@Spy
Alpha alpha;

public void beforeTest() {
    when(alpha.getBeta()).thenReturn(beta);
    when(beta.getCharlie()).thenReturn(charlie);
}

}

另见此。

 类似资料:
  • 我对ScalaMock和嘲笑都是新手。我试图测试一个方法,它调用另一个(mocked)类中的方法,然后在返回的对象上调用方法。 详细资料: 所以我使用ScalaTest,这个测试涉及到五个类... 我正在测试的子指令 在测试中必须被嘲笑的机器 构造机器对象所需的寄存器 我创建为原始机器类的MockableMachine没有空构造函数,因此(据我所知)无法模拟 最后是我的测试类SubInstruct

  • 如果我错了请纠正我,但看起来Moq只能模拟一个公共类,它有一个公共的无参数构造函数,要模拟的方法是。我并不想让这些类公开可见。我是不是错过了一些与Moq的东西,或者只是不适合我想做的事情? 我想我可以创建一个ClassB实现的接口(例如“ICLASSB”),将其注入ClassA,并模拟该接口。ClassB仍然可以是内部的(尽管我意识到接口方法必须是公共的)。虽然这可以工作,但我对创建大量接口感到不

  • 我有一个服务我是这样嘲笑的: } 服务: 我需要能够模拟“CloseableHttpResponse Response = http client . execute(request,clientContext)”,这样“response”对象就是我提前创建的。我希望一些嘲讽的when/then构造可以解决这个问题。我会很感激如何做到这一点的想法。谢谢!

  • 到现在为止,我们都是在Java文件中直接定义类。这样的类出现在包(package)的级别上。Java允许类的嵌套定义。 这里将讲解如何在一个类中嵌套定义另一个类。 嵌套 内部类 Java允许我们在类的内部定义一个类。如果这个类是没有static修饰符,那么这样一个嵌套在内部的类称为内部类(inner class)。 内部类被认为是外部对象的一个成员。在定义内部类时,我们同样有访问权限控制(publ

  • 问题内容: 我有一个适用于我的网站的嵌套集模型,其中包含子类别中的项目,依此类推。除一个我无法解决的问题外,它的工作效果非常好。 使用以下查询: 提供以下输出: 换句话说,不会显示其中没有产品的所有字段。现在到问题了,我想向他们展示COUNT()结果=0。我的查询将如何实现这一点?:) 问题答案: 听起来像是LEFT OUTER JOIN的一项任务,例如: 因此,您确保显示所有类别。请注意,我不确

  • 我试图模拟一个有嵌套类的类。那个嵌套类有一个构造函数参数。当我试图使用mockito而不是mockito测试时,实际的方法正在执行。 我在外部类上做了@injectmock,在内部类上做了@Mock。 我像往常一样尝试使用@Mock调用类,但是实际的方法eth1()正在被访问。 需要模拟内部ClassB方法,而不是访问真实方法。 作为mockito的初学者,我试图澄清这一点。但在访问void方法等