如何使用内部对象创建JUnit测试

时间:2015-10-15 13:23:15

标签: java testing junit mocking mockito

所以我有一个像这样的类结构设置:

public class foo {
    private DomainService service;

    //constructor to initialize

    public Fleet someMethod(Car car) {
        Fleet fleet = new Fleet();
        if(car!=null) {
            Plane plane = service.findObjectByID(car);
            plane.setColor(Blue);
            fleet.addPlane(plane);
        }
        return fleet;
    }
}

public class DomainService {
    List<Plane> planes;

    //constructure to initialize

    public Optional<Plane> findObjectByID(Car car) {
        for(Plane plane : planes) {
            if(plane.getID() == car.getID()) {
                return Optional.of(plane);
            }
        }
        return Optional.absent();
    }
}

public class Fleet {
    List<Plane> planes;
    int ID;
    Date serviceDate;
}

当用户登录到应用程序时,会有很多操作和计算通过spring managed beans发生。他们从数据库中提取有关用户的所有信息并将其存储到对象中。在上面的示例中,当用户登录时,将从其从DB中提取的信息填充平面列表。

我的问题是JUnit测试这个。我的JUnit看起来像这样:

public class fooTest {
    private Foo foo;
    private Car car;

    @Before
    public void setUp() throws Exception {
        foo = new Foo();
    }

    @Test
    public void isBlue() {
        car = new Car;
        car.setID(123);
        Fleet result = foo.someMethod(car);
        assertEquals(Color.BLUE, result.getColor());
    }
}

问题是当用户首次登录时,飞机对象会被初始化,包括飞机ID。哪些是真实世界ID,是一串随机数字和字符。由于这是一项测试,因此飞机不会装满任何真实的东西。即使它填充了真实世界的数据,我也不知道将它设置为什么ID,因为它们是随机的。

所以每次我尝试执行这个JUnit时都会失败,因为findObjectByID总是返回null。

我正在调查嘲讽或ArgumentCaptor,但我是JUnit测试的新手,并且不知道这些是如何工作的,或者他们是否可以在我的情况下提供帮助。关于如何解决这个问题的任何想法?

2 个答案:

答案 0 :(得分:2)

您是否可以使用Spring上下文运行测试:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath*:spring-context.xml" })
    public class fooTest {

        @Inject
        private DomainService service;
        [...]

或模仿您的对象,例如与Mockito框架:

    @RunWith(MockitoJUnitRunner.class)
    public class fooTest {

        private Plane plane;

        @Mock
        private DomainService service;

        @Before
        public void setUp() {
            plane = new Plane();
            when(service.findObjectByID(any(Car.class))).thenReturn(plane);
        }
        [...]

答案 1 :(得分:0)

不一定要始终使用框架,例如:

public class foo 
{
    private final DomainService service;
    private final IFleetFactory fleetFactory;

    public foo(final IFleetFactory factory)
    {
        this.fleetFactory = factory;
    }

    public Fleet someMethod(final Car car) 
    {
        final Fleet fleet = fleetFactory.create();
        final Plane plane = service.findObjectByID(car);
        plane.setColor(Blue);
        fleet.addPlane(plane);
        return fleet;
    }
}

在测试中,您可以使用一个简单的虚拟模型 或IFleetFactory的Mock实例。

但是总的来说,我认为您的课程设计是错误的, 您的方法someMethod仅使用其他类中的方法。 如何使用代码使构造函数成为公共Fleet(汽车,IDomainService服务) of someMethod,您也不会遇到新的问题...