如何模拟已经在类代码中实例化的对象要测试并为其编写存根



我需要测试的类看起来与此相似。我不是在这里写实际课程。

public class Client {
private String country;
private ConnectionImpl conn;
public Client (String country){
    this.country = country;
}
private ConnectionImpl createConnection() {
  SetConnectionImpl impl = new SetConnectionImpl() {
    public String getFirstName() {
      return "Some value";
    }
    public String getLastName() {
      return "Some value";
    }
    public String getAddress() {
      return "Some value";
    }
    public String getPhoneNumber() {
      return "Some value";
    }};
  return new ConnectionImpl("", "", "", "", impl);
}
public String letsDoSomeWork(String requestObject) {
  final ConnectionImpl impl = createConnection();
  String letsHaveSomeResponse = 
  impl.methodTobeStubbed(requestObject);
  return letsHaveSomeResponse;
}
}

现在我写的测试课将看起来像这样。我正在使用Mockito写存根。

@Runwith(MockitoJunitRunner.class)
public class ClientTest {
@Mock
ConnectionImpl impl;
private Client client;
@Before()
public void initialize() {
client = new Client("India");
}
@Test
public void testLetsDoSomework_ShouldReturnString() {
String request = "request";
when(impl.methodTobeStubbed(request)).thenReturn("Response");
String letsHaveSomeResponse = client.letsDoSomeWork(request);
//Now I will make Assertions
}

}

不幸的是,这种固执不起作用,我的假设是,由于要测试的类是在内部创建一个" impl"对象,因此我在这里创建的模拟对象没有被考虑。因此,最终,代码正在输入" Impl"类,该类不应该。

when(impl.methodTobeStubbed(request)).thenReturn("Response");

我使测试案例工作。这是我所做的。

@RunWith(PowerMockRunner.class)
@PrepareForTest(Client.class)
public class ClientTest {
@Mock
ConnectionImpl impl;
private Client client;
@Before()
public void initialize() {
    client = PowerMockito.spy(new Client("India"));
    doReturn(impl).when(client, "createConnection");
}
@Test
public void testLetsDoSomework_ShouldReturnString() {
    String request = "request";
    when(impl.methodTobeStubbed(request)).thenReturn("Response");
    String letsHaveSomeResponse = client.letsDoSomeWork(request);
//Now I will make Assertions
}

您可以使createConnection方法返回模拟连接。

首先,将方法更改为 protected

protected ConnectionImpl createConnection() {
    .... // same code
}

如果该方法是私有的,则不能在测试中模拟它。

然后,在您的测试中,使用Mockito.spy方法:

,用Client对象进行间谍
@Before()
public void initialize() {
    client = Mockito.spy(new Client("India"));
    // letsDoSomeWork method will be called (instead of a mocked version)
    when(client.letsDoSomeWork(anyString())).thenCallRealMethod();
    // createConnection returns your mocked impl object (it doesn't compile if createConnection method is private)
    when(client.createConnection()).thenReturn(impl);
}

然后,当您调用letsDoSomeWork时,它将在Client类中调用真实方法。因此,createConnection将被调用 - 并且由于被模拟,它将返回模拟的impl对象。

注意:确保ClientTest类位于同一Client类中,以使createConnection通过测试可见(即使它们在不同的源文件夹中,例如src/mainsrc/test,也可以假设您使用Maven或Maven或相似 - 包名称必须相同(


另一种做法是为连接制作设置方法:

public class Client {
    private String country;
    private ConnectionImpl conn;
    public Client(String country) {
        this.country = country;
    }
    // create setter method for connection    
    public void setConn(ConnectionImpl conn) {
        this.conn = conn;
    }
    public String letsDoSomeWork(String requestObject) {
        // no need to createConnection
        String letsHaveSomeResponse = 
        this.conn.methodTobeStubbed(requestObject);
        return letsHaveSomeResponse;
    }
}

,您的测试将就像:

@RunWith(MockitoJUnitRunner.class)
public class ClientTest {
    @Mock
    MyConn impl;
    private Client client;
    @Before
    public void initialize() {
        client = new Client("India");
        client.setConn(impl);
    }
    @Test
    public void testLetsDoSomework_ShouldReturnString() {
        String request = "request";
        when(impl.methodTobeStubbed(request)).thenReturn("Response");
        String letsHaveSomeResponse = client.letsDoSomeWork(request);
        // do assertions
    }
}

甚至更好,制作一个接收连接的构造函数:

public Client(String country, ConnectionImpl conn) {
    this.country = country;
    this.conn = conn;
}

和在测试类中:

@Before
public void initialize() {
    client = new Client("India", impl);
}

最新更新