首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用Mockito模拟类的成员变量

使用Mockito模拟类的成员变量
EN

Stack Overflow用户
提问于 2012-01-25 06:58:35
回答 8查看 306.3K关注 0票数 151

我是一个开发新手,尤其是单元测试新手。我想我的要求很简单,但我很想知道其他人对此的想法。

假设我有两个类,像这样-

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

    Second second ;

    public First(){
        second = new Second();
    }

    public String doSecond(){
        return second.doSecond();
    }
}

class Second {

    public String doSecond(){
        return "Do Something";
    }
}

假设我正在编写单元测试来测试First.doSecond()方法。然而,假设我想要这样模拟Second.doSecond()类。我正在使用Mockito来做这件事。

代码语言:javascript
复制
public void testFirst(){
    Second sec = mock(Second.class);
    when(sec.doSecond()).thenReturn("Stubbed Second");

    First first = new First();
    assertEquals("Stubbed Second", first.doSecond());
}

我看到模仿没有生效,断言失败。没有办法模拟我想要测试的类的成员变量。?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-01-25 07:16:05

您需要提供一种访问成员变量的方法,以便可以传递一个mock (最常见的方法是setter方法或接受参数的构造函数)。

如果您的代码没有提供这样做的方法,那么它在TDD (测试驱动开发)中就被错误地分解了。

票数 94
EN

Stack Overflow用户

发布于 2013-07-04 23:58:30

如果你不能改变你的代码,这是不可能的。但是我喜欢依赖注入,并且Mockito支持它:

代码语言:javascript
复制
public class First {    
    @Resource
    Second second;

    public First() {
        second = new Second();
    }

    public String doSecond() {
        return second.doSecond();
    }
}

你的测试:

代码语言:javascript
复制
@RunWith(MockitoJUnitRunner.class)
public class YourTest {
   @Mock
   Second second;

   @InjectMocks
   First first = new First();

   public void testFirst(){
      when(second.doSecond()).thenReturn("Stubbed Second");
      assertEquals("Stubbed Second", first.doSecond());
   }
}

这是非常好和容易的。

票数 71
EN

Stack Overflow用户

发布于 2012-01-25 07:06:27

如果仔细观察代码,您会发现测试中的second属性仍然是Second的实例,而不是模拟(在代码中不会将模拟传递给first )。

最简单的方法是在First类中为second创建一个设置器,并显式地将模拟传递给它。

如下所示:

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

    Second second ;

    public First(){
        second = new Second();
    }

    public String doSecond(){
        return second.doSecond();
    }

    public void setSecond(Second second) {
        this.second = second;
    }


}

class Second {

    public String doSecond(){
        return "Do Something";
    }
}

....

public void testFirst(){
Second sec = mock(Second.class);
when(sec.doSecond()).thenReturn("Stubbed Second");


First first = new First();
first.setSecond(sec)
assertEquals("Stubbed Second", first.doSecond());
}

另一种方法是传递一个Second实例作为First的构造函数参数。

如果你不能修改代码,我想唯一的选择就是使用反射:

代码语言:javascript
复制
public void testFirst(){
    Second sec = mock(Second.class);
    when(sec.doSecond()).thenReturn("Stubbed Second");


    First first = new First();
    Field privateField = PrivateObject.class.
        getDeclaredField("second");

    privateField.setAccessible(true);

    privateField.set(first, sec);

    assertEquals("Stubbed Second", first.doSecond());
}

但你可能可以,因为很少在你不能控制的代码上进行测试(尽管可以想象这样一种场景,你必须测试一个外部库,因为它的作者没有:)

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

https://stackoverflow.com/questions/8995540

复制
相关文章

相似问题

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