首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mockito:嘲笑"Blackbox“属地

Mockito:嘲笑"Blackbox“属地
EN

Stack Overflow用户
提问于 2011-12-22 19:30:36
回答 5查看 7.4K关注 0票数 11

因此,我被要求为我们的开发团队阅读嘲弄和BDD的内容,并使用模拟来改进我们现有的一些单元测试(作为一个实验)。

我最终选择使用Mockito的原因有很多(有些原因超出了我的控制范围),但也就是因为它支持在不适合嘲弄的情况下使用Mockito。

我一整天都在学习Mockito,嘲弄(一般)和BDD。现在,我准备深入研究并开始增强我们的单元测试。

因此,我们有一个名为WebAdaptor的类,它有一个run()方法:

代码语言:javascript
复制
public class WebAdaptor {

    private Subscriber subscriber;

    public void run() {

        subscriber = new Subscriber();
        subscriber.init();
    }
}

请注意:我没有办法修改这段代码(原因超出了这个问题的范围!)因此,我没有能力为Subscriber添加一个setter方法,因此可以认为它是在我的WebAdaptor中不可访问的“黑盒”。

我想编写一个单元测试,它合并了一个Mockito模拟,并将这个模拟用于执行WebAdaptor::run()导致调用Subscriber::init()verify

下面是我到目前为止(在WebAdaptorUnitTest中)所得到的信息:

代码语言:javascript
复制
@Test
public void runShouldInvokeSubscriberInit() {

    // Given
    Subscriber mockSubscriber = mock(Subscriber.class);
    WebAdaptor adaptor = new WebAdaptor();

    // When
    adaptor.run();

    // Then
    verify(mockSubscriber).init();
}

当我运行这个测试时,实际的Subscriber::init()方法将被执行(从控制台输出和看到本地系统上正在生成的文件中可以看出),而不是mockSubscriber,它不应该做任何事情(或返回任何事情)。

我已经检查并重新检查了:initpublic,不是staticfinal,它返回void。根据文档,Mockito应该没有问题来模拟这个对象。

因此,它让我思考:我需要明确地将mockSubscriberadaptor联系起来吗?如果是这种情况,那么通常情况下,以下方法通常会解决这个问题:

代码语言:javascript
复制
adaptor.setSubscriber(mockSubscriber);

但是,由于我不能添加任何这样的设置(请阅读我上面的笔记),我不知道如何才能强制这样一个协会。因此,有几个非常密切相关的问题:

  • 有人能确认我已经正确设置了测试(使用Mockito )吗?
  • 我对失踪策划人的怀疑是正确的吗?(是否需要通过setter将这些对象关联起来?)
  • 如果我以上的怀疑是真的,而且我不能修改WebAdaptor,我有什么规避措施吗?

提前感谢!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-12-22 19:44:39

您需要将模拟注入正在测试的类中。您不需要访问订阅服务器。mockito和其他模拟框架的帮助之处在于,您不需要访问正在与其交互的对象。但是,您确实需要一种方法来将模拟对象导入您正在测试的类中。

代码语言:javascript
复制
public class WebAdaptor {

    public WebAdaptor(Subscriber subscriber) { /* Added a new constructor */
       this.subscriber = subscriber;
    }

    private Subscriber subscriber;

    public void run() {
        subscriber.init();
    }
}

现在,您可以在模拟上而不是在实际对象上验证您的交互。

代码语言:javascript
复制
@Test
public void runShouldInvokeSubscriberInit() {

    // Given
    Subscriber mockSubscriber = mock(Subscriber.class);
    WebAdaptor adaptor = new WebAdaptor(mockSubscriber);  // Use the new constructor

    // When
    adaptor.run();

    // Then
    verify(mockSubscriber).init();
}

如果向构造函数添加订阅服务器不是正确的方法,则还可以考虑使用工厂来允许WebAdaptor从您控制的工厂实例化新的订阅服务器对象。然后,可以将工厂模拟为提供者模拟订阅服务器。

票数 10
EN

Stack Overflow用户

发布于 2011-12-22 19:53:59

如果您不想更改生产代码,并且仍然能够模拟订阅者类的功能,那么您应该看看PowerMock。它与Mockito一起工作很好,并允许您模拟新对象的创建。

代码语言:javascript
复制
Subscriber mockSubscriber = mock(Subscriber.class);
whenNew(Subscriber.class).withNoArguments().thenReturn(mockSubscriber);

进一步的细节将在PowerMock文档框架中解释。

票数 5
EN

Stack Overflow用户

发布于 2011-12-26 15:41:23

有一种方法可以将模拟注入到被测试的类中,而无需对代码进行任何修改。这可以使用Mockito WhiteBox来完成。这是一个非常好的特性,可以用来从测试中注入类的依赖项。下面是一个关于它如何工作的简单示例,

代码语言:javascript
复制
@Mock
Subscriber mockSubscriber;
WebAdaptor cut = new WebAdaptor();

@Before
public void setup(){
    //sets the internal state of the field in the class under test even if it is private
    MockitoAnnotations.initMocks(this);

    //Now the whitebox functionality injects the dependent object - mockSubscriber
    //into the object which depends on it - cut
    Whitebox.setInternalState(cut, "subscriber", mockSubscriber);
}

@Test
public void runShouldInvokeSubscriberInit() {
    cut.run();
    verify(mockSubscriber).init();
}

希望这会有所帮助:)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8608826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档