无法模拟构造函数中的方法

时间:2019-03-21 23:35:32

标签: java mockito junit4 powermockito

这是我的第一堂课,其中构造函数有一个对象在其他课中调用方法。

Class Search{

public Search(String username, JSONObject accounts) throws Exception {

        Credentials credentials = new Credentials(username);
        String Uid = credentials.getUserName();
        String Pwd = new String(credentials.getCredentials().getPassword());
    }

public getDOB(){
 --------------------
 -------------
}
}   

类凭证:

import javax.resource.spi.security.PasswordCredential;  
Public class Credentials{

    public Credentials(String name){

    }

    public PasswordCredential getCredentials(){
        return passwordCredential;
    }

    public String getUserName(){
        PasswordCredential localCredential = getCredentials();
        return localCredential.getUsername();
    }
}

班级考试:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Search.class, Credentials.class})
public class JunitTest {

  @Test
      public void playTest() {
        PasswordCredential pwdCreds = new PasswordCredential();
        pwdCreds.setPassword("test");

        Credentials credentials = new Credentials("user");
        Credentials credentials = Mockito.spy(credentials);
        Mockito.doReturn(pwdCreds).when(credentials).getCredentials();
        Mockito.doReturn("cmApptest").when(credentials).getUserName();

        Search search = new Search("username", jsonobject);
        search.getDOB();

      }

}

每当我调试测试类时,即使模拟了它们,它也会执行getCredentialsgetUserName方法。我期望实际的方法不执行,相反,它应该返回在JunitTest类中提到的值。

1 个答案:

答案 0 :(得分:1)

您不会用模拟代替在Search类中使用的真实版本的凭据。相反,您显然是在Search对象的构造函数中创建并使用一个真实的Credentials对象。为了使模拟工作正常,您必须用模拟实际替换Search对象中的凭据对象。只需在代码中的某个地方创建相同类型的模拟,就不会导致它替换代码中其他地方的真实对象的实例。

通常,依赖注入用于引入模拟,就像使用Spring一样。这是做您想要的简单方法。重新定义您的Search构造函数,如下所示:

class Search {
    Search(String username, JSONObject accounts, Credentials creds) throws Exception {
        Credentials credentials = creds? creds : new Credentials(username);
        String Uid = credentials.getUserName();
        String Pwd = new String(credentials.getCredentials().getPassword());
    }
    Search(String username, JSONObject accounts) throws Exception {
        this(username, accounts, null);
    }
}

您的生产代码的行为不会受到影响,但是您可以选择使用模拟构建Search。

    Credentials credentials = new Credentials("user");
    Credentials credentials1 = Mockito.spy(credentials);
    Mockito.doReturn(pwdCreds).when(credentials1).getCredentials();
    Mockito.doReturn("cmApptest").when(credentials1).getUserName();

    Search search = new Search("username", jsonobject, credentials1);
    search.getDOB();

使用模拟而不是真实对象在代码方面没有任何魔术。模拟框架仅使您可以轻松创建以非常特定的方式进行测试的替代对象。您仍然必须使这些对象被您的代码使用。

此外,您实际上并不需要/想要间谍。您确实需要一个模拟,因为您正在定义凭据中所有方法的行为。使用模拟,您根本不需要实例化凭据对象。因此,我上面给出的测试代码的第一行可能是:

Credentials credentials1 = Mockito.mock(Credentials.class);

(或类似的东西。我实际上并没有尝试这段代码)