【问题标题】:How to JUnit Test with internal object creation如何使用内部对象创建进行 JUnit 测试
【发布时间】:2015-10-15 13:23:14
【问题描述】:

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

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 托管的 bean 发生的。他们从数据库中提取有关用户的所有信息并将其存储到对象中。在上面的示例中,当用户登录时,飞机列表是根据从数据库中提取的信息填充的。

我的问题是 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。

我正在研究 mocking 或 ArgumentCaptor,但我是 JUnit 测试的新手,我真的不知道它们是如何工作的,或者它们是否可以帮助我的情况。有关如何解决此问题的任何想法?

【问题讨论】:

    标签: java testing junit mocking mockito


    【解决方案1】:

    您可以是否使用 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);
            }
            [...]
    

    【讨论】:

    • 什么是 any() 调用,因为我遇到了语法错误。
    • any() 是 Mockito 的一个静态方法,它表示可以为该参数传递任何内容。你得到一个语法错误 b/c 它需要传递该参数的类,所以它应该是any(Car.class))。 Matchers 文档:mockito.googlecode.com/hg-history/1.6/javadoc/org/mockito/…
    【解决方案2】:

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

    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;
        }
    }
    

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

    但总的来说,我认为您的课程设计是错误的, 您的方法 someMethod 仅使用其他类的方法。 用代码让构造函数 public Fleet(Car car, IDomainService service) 怎么样 的 someMethod ,你也没有新的问题......

    【讨论】:

      猜你喜欢
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多