模拟封装集合的对象

发布于 2024-12-10 01:06:57 字数 3813 浏览 1 评论 0原文

我想知道如何检查方法是否返回封装某个集合的容器,该集合是模拟对象返回的多个其他容器的聚合。也就是说,它包含各个容器的所有元素。我在其他地方有一些测试来检查容器“是否有效”(add/addAll/etc),所以我知道这是有效的,但我不确定如何进行“createsRoadUsersAccordingToAllAddedCreators”下面的测试。

我有一个 RoadUserCreationDaemon 类,我称之为 create ,它根据添加的 RoadUserCreator 返回一个 RoadUserContainer 。简化版本:

public class RoadUserCreationDaemon {

    private SimulationManager simulationManager;
    private List<RoadUserCreator> roadUserCreators;

    public RoadUserCreationDaemon(SimulationManager simulationManager) {
        this.simulationManager = simulationManager;
        roadUserCreators = new ArrayList<RoadUserCreator>();
    }

    public void addRoadUserCreator(RoadUserCreator roadUserCreator) {
        roadUserCreators.add(roadUserCreator);
    }

    public RoadUserContainer createRoadUsers() {
        RoadUserContainer roadUsers = new RoadUserContainerImpl(); 
        for (RoadUserCreator creator : roadUserCreators) {
            roadUsers.addAll(createRoadUsers(creator));
        }
        return roadUsers;
    }

    public RoadUserContainer createRoadUsers(
            RoadUserCreator roadUserCreator) {
        return roadUserCreator.create();
    }
}

我首先为 createRoadUsers 编写一个测试(JUnit4 / JMock2.5.1),它返回带有提供的创建者的 RoadUserContainer。然后我开始为非参数化的 createRoadUsers 编写一个测试,看看它是否返回一个容器,其中包含创建者返回的各个容器的所有元素:

@RunWith(JMock.class)
public class TestRoadUserCreationDaemon {
    Mockery context = new JUnit4Mockery();      
    private RoadUserCreationDaemon daemon;      
    private RoadUserCreator roadUserCreator;    
    private SimulationManager simulationManager;        
    private RoadUserContainer createdRoadUsers;

    @Before
    public void setUp() {
        simulationManager = context.mock(SimulationManager.class);
        daemon = new RoadUserCreationDaemon(simulationManager);

        roadUserCreator = context.mock(RoadUserCreator.class);
        createdRoadUsers = context.mock(RoadUserContainer.class);
    }       

    @Test
    public void createsRoadUsersAccordingToAllAddedCreators() throws Exception {
        final RoadUserCreator anotherRoadUserCreator = context.mock(RoadUserCreator.class, "anotherRUC");
        final RoadUserContainer moreCreatedRoadUsers = context.mock(RoadUserContainer.class, "moreCRU");
        context.checking(new Expectations() {{
            oneOf (roadUserCreator).create(); will(returnValue(createdRoadUsers));
            oneOf (anotherRoadUserCreator).create(); will(returnValue(moreCreatedRoadUsers));

            oneOf (createdRoadUsers).roadUsersAsList();
            oneOf (moreCreatedRoadUsers).roadUsersAsList();
        }});

        daemon.addRoadUserCreator(roadUserCreator);
        daemon.addRoadUserCreator(anotherRoadUserCreator);
        daemon.createRoadUsers();

        //how to easily check that the two lists are equivilant - have same items, but not the same object?
        //assertEquals(createdRoadUsers, daemon.createRoadUsers() );
    }

    @Test
    public void createsRoadUsersAccordingToCreator() throws Exception {

        context.checking(new Expectations() {{
            oneOf (roadUserCreator).create(); will(returnValue(createdRoadUsers));
        }});
        assertEquals(createdRoadUsers, daemon.createRoadUsers(roadUserCreator));
    }
}

正如评论所说......我不知道如何在非参数化的情况下继续进行-丑陋的方式。

“RoadUserContainer”界面:

public interface RoadUserContainer extends Iterable<RoadUser> {
    public void add(RoadUser roadUser);
    public Iterator<RoadUser> iterator();
    public void addAll(RoadUserContainer createRoadUsers);
    public List<RoadUser> roadUsersAsList();
    public boolean equals(RoadUserContainer otherContainer);
    ...
}

我是 TDD 和模拟的新手,这是我 6 年多以来的第一个 Java 项目,所以请随意评论辅助美观!

I'm wondering how to go about checking that a method returns a container encapsulating some collection which is the aggregate of multiple other containers returned by mock objects. That is, it contains all the elements of the individual containers. I have some tests elsewhere that check the container 'works' (add/addAll/etc), so I know that works, but I'm not sure how go about with the test below 'createsRoadUsersAccordingToAllAddedCreators'.

I have a RoadUserCreationDaemon class which I call create upon which returns a RoadUserContainer according to added RoadUserCreator's. A simplified version:

public class RoadUserCreationDaemon {

    private SimulationManager simulationManager;
    private List<RoadUserCreator> roadUserCreators;

    public RoadUserCreationDaemon(SimulationManager simulationManager) {
        this.simulationManager = simulationManager;
        roadUserCreators = new ArrayList<RoadUserCreator>();
    }

    public void addRoadUserCreator(RoadUserCreator roadUserCreator) {
        roadUserCreators.add(roadUserCreator);
    }

    public RoadUserContainer createRoadUsers() {
        RoadUserContainer roadUsers = new RoadUserContainerImpl(); 
        for (RoadUserCreator creator : roadUserCreators) {
            roadUsers.addAll(createRoadUsers(creator));
        }
        return roadUsers;
    }

    public RoadUserContainer createRoadUsers(
            RoadUserCreator roadUserCreator) {
        return roadUserCreator.create();
    }
}

I started by writing a test (JUnit4 / JMock2.5.1) for createRoadUsers which returns a RoadUserContainer with a supplied creator. Then I started writing a test for a non-parameterised createRoadUsers to see if it returns a container with all the elements of the individual containers returned by the creators:

@RunWith(JMock.class)
public class TestRoadUserCreationDaemon {
    Mockery context = new JUnit4Mockery();      
    private RoadUserCreationDaemon daemon;      
    private RoadUserCreator roadUserCreator;    
    private SimulationManager simulationManager;        
    private RoadUserContainer createdRoadUsers;

    @Before
    public void setUp() {
        simulationManager = context.mock(SimulationManager.class);
        daemon = new RoadUserCreationDaemon(simulationManager);

        roadUserCreator = context.mock(RoadUserCreator.class);
        createdRoadUsers = context.mock(RoadUserContainer.class);
    }       

    @Test
    public void createsRoadUsersAccordingToAllAddedCreators() throws Exception {
        final RoadUserCreator anotherRoadUserCreator = context.mock(RoadUserCreator.class, "anotherRUC");
        final RoadUserContainer moreCreatedRoadUsers = context.mock(RoadUserContainer.class, "moreCRU");
        context.checking(new Expectations() {{
            oneOf (roadUserCreator).create(); will(returnValue(createdRoadUsers));
            oneOf (anotherRoadUserCreator).create(); will(returnValue(moreCreatedRoadUsers));

            oneOf (createdRoadUsers).roadUsersAsList();
            oneOf (moreCreatedRoadUsers).roadUsersAsList();
        }});

        daemon.addRoadUserCreator(roadUserCreator);
        daemon.addRoadUserCreator(anotherRoadUserCreator);
        daemon.createRoadUsers();

        //how to easily check that the two lists are equivilant - have same items, but not the same object?
        //assertEquals(createdRoadUsers, daemon.createRoadUsers() );
    }

    @Test
    public void createsRoadUsersAccordingToCreator() throws Exception {

        context.checking(new Expectations() {{
            oneOf (roadUserCreator).create(); will(returnValue(createdRoadUsers));
        }});
        assertEquals(createdRoadUsers, daemon.createRoadUsers(roadUserCreator));
    }
}

As the comment says...I'm not sure how to proceed in a non-ugly way.

The 'RoadUserContainer' interface:

public interface RoadUserContainer extends Iterable<RoadUser> {
    public void add(RoadUser roadUser);
    public Iterator<RoadUser> iterator();
    public void addAll(RoadUserContainer createRoadUsers);
    public List<RoadUser> roadUsersAsList();
    public boolean equals(RoadUserContainer otherContainer);
    ...
}

I am new to TDD and mocking, and this is my first Java project for >6 years, so feel free to comment on ancillary aesthetics!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青春如此纠结 2024-12-17 01:06:57

我最初可能会使用真实的容器并模拟其他对象。然后使用 hamcrest 询问生成的对象。

我想要创建的测试看起来像这样:

final RoadUser roadUser0 = context.mock(RoadUser.class, "roadUser0");
final RoadUser roadUser1 = context.mock(RoadUser.class, "roadUser1");
final RoadUser roadUser2 = context.mock(RoadUser.class, "roadUser2");

final RoadUserCreator roadUserCreator0 = context.mock(RoadUserCreator.class, "roadUserCreator0");
final RoadUserCreator roadUserCreator1 = context.mock(RoadUserCreator.class, "roadUserCreator1");

final RoadUserCreationDaemon daemon = new RoadUserCreationDaemon(null);
daemon.addRoadUserCreator(roadUserCreator0);
daemon.addRoadUserCreator(roadUserCreator1);        

context.checking(new Expectations() {{
    oneOf(roadUserCreator0).create(); will(returnValue(roadUsers(roadUser0, roadUser1)));
    oneOf(roadUserCreator1).create(); will(returnValue(roadUsers(roadUser2)));
}});

assertThat(daemon.createRoadUsers(), contains(roadUser0, roadUser1, roadUser2));

您将需要从 hamcrest 导入这些内容:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;

如果顺序不重要,您可以使用 containsInAnyOrder 而不是 contains

您还需要创建实用程序方法“roadUsers”

public static RoadUserContainer roadUsers(final RoadUser... roadUsers)
{
    return new RoadUserContainerImpl(roadUsers);
}

另一种设计是更改 RoadUserCreationDaemon 的接口

public void createRoadUsers(final RoadUserContainer roadUsers) {
    for (final RoadUserCreator roadUserCreator : roadUserCreators) {
        roadUsers.addAll(roadUserCreator.create());
    }
}

然后您可以像这样编写测试:

final RoadUserContainer roadUserContainer0 = context.mock(RoadUserContainer.class, "roadUserContainer0");
final RoadUserContainer roadUserContainer1 = context.mock(RoadUserContainer.class, "roadUserContainer1");

final RoadUserContainer resultRoadUserContainer = context.mock(RoadUserContainer.class, "resultRoadUserContainer");

final RoadUserCreator roadUserCreator0 = context.mock(RoadUserCreator.class, "roadUserCreator0");
final RoadUserCreator roadUserCreator1 = context.mock(RoadUserCreator.class, "roadUserCreator1");

final RoadUserCreationDaemon daemon = new RoadUserCreationDaemon(null);
daemon.addRoadUserCreator(roadUserCreator0);
daemon.addRoadUserCreator(roadUserCreator1);

context.checking(new Expectations() {
    {
        oneOf(roadUserCreator0).create();
        will(returnValue(roadUserContainer0));
        oneOf(roadUserCreator1).create();
        will(returnValue(roadUserContainer1));

        oneOf(resultRoadUserContainer).addAll(roadUserContainer0);
        oneOf(resultRoadUserContainer).addAll(roadUserContainer1);
    }
});

daemon.createRoadUsers(resultRoadUserContainer);

如果调用“addAll”的顺序很重要,您可以使用 jmock 序列

I would probably initially use real containers and mock the other objects. Then use hamcrest to interrogate the resulting object.

The test I would want to create would look something like this:

final RoadUser roadUser0 = context.mock(RoadUser.class, "roadUser0");
final RoadUser roadUser1 = context.mock(RoadUser.class, "roadUser1");
final RoadUser roadUser2 = context.mock(RoadUser.class, "roadUser2");

final RoadUserCreator roadUserCreator0 = context.mock(RoadUserCreator.class, "roadUserCreator0");
final RoadUserCreator roadUserCreator1 = context.mock(RoadUserCreator.class, "roadUserCreator1");

final RoadUserCreationDaemon daemon = new RoadUserCreationDaemon(null);
daemon.addRoadUserCreator(roadUserCreator0);
daemon.addRoadUserCreator(roadUserCreator1);        

context.checking(new Expectations() {{
    oneOf(roadUserCreator0).create(); will(returnValue(roadUsers(roadUser0, roadUser1)));
    oneOf(roadUserCreator1).create(); will(returnValue(roadUsers(roadUser2)));
}});

assertThat(daemon.createRoadUsers(), contains(roadUser0, roadUser1, roadUser2));

you will need these imports from hamcrest:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;

If order is not important you could use containsInAnyOrder instead of contains

you would also need to create the utility method "roadUsers"

public static RoadUserContainer roadUsers(final RoadUser... roadUsers)
{
    return new RoadUserContainerImpl(roadUsers);
}

An alternative design would be to change the interface of the RoadUserCreationDaemon

public void createRoadUsers(final RoadUserContainer roadUsers) {
    for (final RoadUserCreator roadUserCreator : roadUserCreators) {
        roadUsers.addAll(roadUserCreator.create());
    }
}

Then you could write the tests like this:

final RoadUserContainer roadUserContainer0 = context.mock(RoadUserContainer.class, "roadUserContainer0");
final RoadUserContainer roadUserContainer1 = context.mock(RoadUserContainer.class, "roadUserContainer1");

final RoadUserContainer resultRoadUserContainer = context.mock(RoadUserContainer.class, "resultRoadUserContainer");

final RoadUserCreator roadUserCreator0 = context.mock(RoadUserCreator.class, "roadUserCreator0");
final RoadUserCreator roadUserCreator1 = context.mock(RoadUserCreator.class, "roadUserCreator1");

final RoadUserCreationDaemon daemon = new RoadUserCreationDaemon(null);
daemon.addRoadUserCreator(roadUserCreator0);
daemon.addRoadUserCreator(roadUserCreator1);

context.checking(new Expectations() {
    {
        oneOf(roadUserCreator0).create();
        will(returnValue(roadUserContainer0));
        oneOf(roadUserCreator1).create();
        will(returnValue(roadUserContainer1));

        oneOf(resultRoadUserContainer).addAll(roadUserContainer0);
        oneOf(resultRoadUserContainer).addAll(roadUserContainer1);
    }
});

daemon.createRoadUsers(resultRoadUserContainer);

If the order of the calls to "addAll" is important you can use a jmock sequence

将军与妓 2024-12-17 01:06:57

我想我会嘲笑造物主,但让它返回真正的容器。测试的目的是确保守护进程调用了创建者的所有创建方法,对吧?所以你的测试条件看起来像

  RoadUserContainer result = daemon.createRoadUsers();

  // Check that the result contains both creator's users
  Assert.assertEquals(createdRoadUsers.size() + moreCreatedRoadUsers.size(), result.size());

  for (RoadUser user : createdRoadUsers)
      Assert.assertTrue(result.contains(user));
  for (RoadUser user : moreCreatedRoadUsers)
      Assert.assertTrue(result.contains(user));

I think I would mock the Creator but have it return real Containers. The idea of the test is to make sure that the Daemon invoked all of the creator's create methods, right? So your test condition would look like

  RoadUserContainer result = daemon.createRoadUsers();

  // Check that the result contains both creator's users
  Assert.assertEquals(createdRoadUsers.size() + moreCreatedRoadUsers.size(), result.size());

  for (RoadUser user : createdRoadUsers)
      Assert.assertTrue(result.contains(user));
  for (RoadUser user : moreCreatedRoadUsers)
      Assert.assertTrue(result.contains(user));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文