如何在构造函数中模拟实例?

时间:2018-06-14 18:00:10

标签: java junit mocking mockito junit5

我有一个班级

public class MockSampleUser {

    private Address address = null;

    public MockSampleUser(){
        address = new Address();
    }

    public String getAddress(){
        return address.getAddress();
    }

    class Address {
        public String getAddress(){
            return "Address";
        }
    }

}

单元测试:

import static org.junit.Assert.*;
import org.junit.Test;
import static org.mockito.Mockito.*;

public class MockSampleUserTest {

    @Test
    public void MockSampleUser(){

        MockSampleUser.Address address = mock(MockSampleUser.Address.class);
        MockSampleUser mockSampleUser = spy(MockSampleUser.class);

        when(address.getAddress()).thenReturn("New Address");
        String add = mockSampleUser.getAddress();
        assertEquals("New Address", add);

        add = mockSampleUser.getAddress();
        assertEquals("Address", add);
    }
}

我想写一个测试,当我调用类MockSampleUser的getAddress时它将返回" New Address"。 我想写一个测试,当我调用类MockSampleUser的getAddress时它将返回"新地址"。

1 个答案:

答案 0 :(得分:1)

Mocking旨在模拟被测对象的依赖关系,而不是模拟实现细节 实际上address不是客户可以设置的依赖项,因此您无法通过Mockito模拟它。
您应该做的是重载构造函数/更改实际构造函数以接受Address参数,或者如果依赖项是可变的,则为此字段提供setter。
例如,使用构造函数:

public MockSampleUser(){
    address = new Address();
}

public MockSampleUser(Address){
    this.address = address;
}

例如使用setter:

public void setAddress(Address){
    this.address = address;
}

请注意,关于您的单元测试,您希望getAddress()在多次调用时返回不同的内容:

String add = mockSampleUser.getAddress();
assertEquals("New Address", add);

add = mockSampleUser.getAddress();
assertEquals("Address", add);

它没有意义,因为它引用了同一个对象,并且它的状态在两个断言之间没有改变。

如果你不允许地址依赖是可变的,那么你的测试应该看起来像是(间谍在这里是无助的,大多数情况下都是正确的):

@Test
public void MockSampleUser(){
    MockSampleUser.Address address = mock(MockSampleUser.Address.class);
    MockSampleUser mockSampleUser = new MockSampleUser(address);
    when(address.getAddress()).thenReturn("New Address");

    String add = mockSampleUser.getAddress();
    assertEquals("New Address", add);
    // or better, use the address object itself as expected
    assertEquals(address.getAddress(), add);
}

如果你允许地址依赖是可变的,那么应该优先使用setter,并且你可以断言被测对象的before / after状态:

@Test
public void MockSampleUser(){
    MockSampleUser mockSampleUser = new MockSampleUser();
    // before setting the address
    assertEquals("Address", mockSampleUser.getAddress());

    // after setting the address
    MockSampleUser.Address address = mock(MockSampleUser.Address.class);
    mockSampleUser.setAddress(address);
    when(address.getAddress()).thenReturn("New Address");
    String add = mockSampleUser.getAddress();
    assertEquals("New Address", add);
    // or better, use the address object itself as expected
    assertEquals(address.getAddress(), add);
}