如何编写单元测试以验证函数是否对其结果进行排序?

时间:2013-07-16 21:29:50

标签: java unit-testing junit easymock

我有一个数据源,我可以从中请求一个(任何)国家/地区的人员列表,以及一种从该数据源检索人员并按名称按字母顺序对其进行排序的方法。我应该如何编写单元测试以确保方法的排序部分正常工作?

这就是我的SUT的样子:

class PeopleStuff {

    public IData data;

    public List<Person> getSortedPeopleForCountry(String countryName) {
        List<Person> people = data.getPeopleForCountry(countryName);

        Comparator nameComparator = new PersonNameComparator();
        Collections.sort(people, nameComparator);

        return people;
    }

}

这就是我的单元测试:

@Test public void testGetPeopleSortsByPeopleName() {
    String COUNTRY = "Whatistan";

    // set up test (the 3 lines below are actually in a @Before setup method)
    PeopleStuff peopleStuff = new PeopleStuff();
    IData mockData = createNiceMock(IData.class);
    peopleStuff.data = mockData;

    // set up data
    List<PersonName> mockPeopleList = new ArrayList<PersonName>();
    mockPeopleList.add(new Person(COUNTRY, "A"));
    mockPeopleList.add(new Person(COUNTRY, "D"));
    mockPeopleList.add(new Person(COUNTRY, "B"));
    mockPeopleList.add(new Person(COUNTRY, "C"));

    when(mockData.getPeopleForCountry(COUNTRY)).thenReturn(mockPeopleList);

    // exercise
    List<String> result = peopleStuff.getSortedPeopleForCountry(COUNTRY);

    // assert
    assertEquals("A", result.get(0).name);
    assertEquals("B", result.get(1).name);
    assertEquals("C", result.get(2).name);
    assertEquals("D", result.get(3).name);
}

我需要知道的是,我是如何对数据进行存根,运行测试并使断言正确,或者是否有更好的方法来执行此操作。

我的应用程序有很多测试方法和很多自定义排序算法;我实现了所有测试以使用我编写的4个值in a "random" order,这是我在编写测试时选择的。


我应该测试比较器是否被调用?这对我来说似乎不对,因为我不知道他们是否需要正确的数据,或者是在getSortedPeopleForCountry()内的算法中的正确时间。我想检测这样的情况:

public List<Person> getSortedPeopleForCountry(String countryName) {
    List<Person> people = data.getPeopleForCountry(countryName);

    Comparator nameComparator = new PersonNameComparator();
    List<Person> sortedPeople = new ArrayList<Person>(people)
    Collections.sort(sortedPeople, nameComparator);

    return people; // oops!
}

我是否应该像这样添加添加使用真实比较器的模拟比较器,同时验证它们是否被调用?

我做得对吗?

3 个答案:

答案 0 :(得分:2)

我认为您当前的测试非常好 - 测试是现实的,执行所有代码,并且您正在嘲笑数据源&amp;使用依赖注入来提供模拟数据源。在这个测试中有很多最佳实践。

关于你是否应该嘲笑比较器的问题(因此在testGetPeopleSortsByPeopleName进行纯单元测试),你肯定会得到两个不同的意见:

  • 纯粹主义者认为你的测试在技术上是一个集成测试,要进行适当的单元测试,你需要调整测试以使用模拟比较器,然后单独测试比较器。
  • 实用主义者会争辩说你的测试已经是高质量的,并且它并不重要,因为它不是最严格意义上的单元测试。此外,将其拆分为两个单独的单元测试可能会使测试的可读性降低 - 如果您涉及模拟比较器,我认为上述测试就是这种情况。

我个人认为你应该保持原样,事实上你有一个高质量,可读的测试,可以运行所有代码并有效地断言你的要求,这比担心严格纯粹的单元测试要重要得多。

测试看起来需要改进的唯一方法是测试方法的长度 - 我认为一点方法提取可以帮助提高可读性并使测试方法更具表现力。我会瞄准这样的事情:

@Test public void testGetPeopleSortsByPeopleName() {

    peopleStuff.data = buildMockDataSource(COUNTRY, "A", "D", "B", "C")

    List<String> result = peopleStuff.getSortedPeopleForCountry(COUNTRY);

    assertPersonList(result, "A", "B", "C", "D")
}

private IData buildMockDataSource(String country, String ... names) {
    ...
}

private void assertPersonList(List<Person> people, String ... names) {
    ...
}

答案 1 :(得分:1)

将排序逻辑与返回列表分开。所以我有getPeopleForCountry(String countryName)只返回一个列表,而排序列表将从getSortedPeopleForCountry(List)返回。这样您就可以在排序之前和之后测试它的工作原理。此外,您可能希望覆盖Equals()方法来比较名称,如果这是你想要的,但后来你想要与其他一些属性进行比较。那是你的电话。

答案 2 :(得分:0)

    <container class="container-fluid">
      <!--START OF ROW-->
      <div class="row">

        <!--Product Start-->
        <div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
          </div>
          <div class="image">
            <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
          </div>
          <div class="title">
            <h6>Rockaway Salt Spray, 4.2 oz</h6>
          </div>
          <div class="brand">
            <h6>By R+Co</h6>
          </div>
          <div class="col-4-4">
            <div class="social-footer">
              <div class="col-4-4 trending">
                <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"><span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
                    <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
              </div>
              <div class="image">
                <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
              </div>
              <div class="title">
                <h6>Rockaway Salt Spray, 4.2 oz</h6>
              </div>
              <div class="brand">
                <h6>By R+Co</h6>
              </div>
              <div class="col-4-4">
                <div class="social-footer">
                  <div class="col-4-4 trending">
                    <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"><span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
                    <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                  </div>
                  <div class="image">
                    <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                  </div>
                  <div class="title">
                    <h6>Rockaway Salt Spray, 4.2 oz</h6>
                  </div>
                  <div class="brand">
                    <h6>By R+Co</h6>
                  </div>
                  <div class="col-4-4">
                    <div class="social-footer">
                      <div class="col-4-4 trending">
                        </span>
                        <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"></span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
        <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                      </div>
                      <div class="image">
                        <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                      </div>
                      <div class="title">
                        <h6>Rockaway Salt Spray, 4.2 oz</h6>
                      </div>
                      <div class="brand">
                        <h6>By R+Co</h6>
                      </div>
                      <div class="col-4-4">
                        <div class="social-footer">
                          <div class="col-4-4 trending">
                            <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"><span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
                    <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                          </div>
                          <div class="image">
                            <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                          </div>
                          <div class="title">
                            <h6>Rockaway Salt Spray, 4.2 oz</h6>
                          </div>
                          <div class="brand">
                            <h6>By R+Co</h6>
                          </div>
                          <div class="col-4-4">
                            <div class="social-footer">
                              <div class="col-4-4 trending">
                                <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"><span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
                    <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                              </div>
                              <div class="image">
                                <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                              </div>
                              <div class="title">
                                <h6>Rockaway Salt Spray, 4.2 oz</h6>
                              </div>
                              <div class="brand">
                                <h6>By R+Co</h6>
                              </div>
                              <div class="col-4-4">
                                <div class="social-footer">
                                  <div class="col-4-4 trending">
                                    </span>
                                    <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"></span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
          <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                                  </div>
                                  <div class="image">
                                    <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                                  </div>
                                  <div class="title">
                                    <h6>Rockaway Salt Spray, 4.2 oz</h6>
                                  </div>
                                  <div class="brand">
                                    <h6>By R+Co</h6>
                                  </div>
                                  <div class="col-4-4">
                                    <div class="social-footer">
                                      <div class="col-4-4 trending">
                                        <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"><span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
                    <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                                      </div>
                                      <div class="image">
                                        <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                                      </div>
                                      <div class="title">
                                        <h6>Rockaway Salt Spray, 4.2 oz</h6>
                                      </div>
                                      <div class="brand">
                                        <h6>By R+Co</h6>
                                      </div>
                                      <div class="col-4-4">
                                        <div class="social-footer">
                                          <div class="col-4-4 trending">
                                            <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"><span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
                    <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                                          </div>
                                          <div class="image">
                                            <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                                          </div>
                                          <div class="title">
                                            <h6>Rockaway Salt Spray, 4.2 oz</h6>
                                          </div>
                                          <div class="brand">
                                            <h6>By R+Co</h6>
                                          </div>
                                          <div class="col-4-4">
                                            <div class="social-footer">
                                              <div class="col-4-4 trending">
                                                </span>
                                                <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"></span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
         <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                                              </div>
                                              <div class="image">
                                                <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                                              </div>
                                              <div class="title">
                                                <h6>Rockaway Salt Spray, 4.2 oz</h6>
                                              </div>
                                              <div class="brand">
                                                <h6>By R+Co</h6>
                                              </div>
                                              <div class="col-4-4">
                                                <div class="social-footer">
                                                  <div class="col-4-4 trending">
                                                    <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"><span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
                    <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                                                  </div>
                                                  <div class="image">
                                                    <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                                                  </div>
                                                  <div class="title">
                                                    <h6>Rockaway Salt Spray, 4.2 oz</h6>
                                                  </div>
                                                  <div class="brand">
                                                    <h6>By R+Co</h6>
                                                  </div>
                                                  <div class="col-4-4">
                                                    <div class="social-footer">
                                                      <div class="col-4-4 trending">
                                                        <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"><span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
                    <!--Product Start--><div class="col-4-4 tile">
          <div class="price">
            <h4>32.99</h4>
                                                      </div>
                                                      <div class="image">
                                                        <img class="center-block" src="https://res.cloudinary.com/hcu8jcnmr/image/upload/c_fit,w_600,h_600/ichx6rlctigutk8qd0ky.jpg">
                                                      </div>
                                                      <div class="title">
                                                        <h6>Rockaway Salt Spray, 4.2 oz</h6>
                                                      </div>
                                                      <div class="brand">
                                                        <h6>By R+Co</h6>
                                                      </div>
                                                      <div class="col-4-4">
                                                        <div class="social-footer">
                                                          <div class="col-4-4 trending">
                                                            </span>
                                                            <h4>Trending<h4>
        </div>
            <div class="col-4-4 likes">
              <span class="fa fa-heart"></span>
          </div>
            </div>
      </div>
    </div><!--Product END-->
     </div><!--END OF ROW-->




            </container

此代码表示一个示例,其中ArrayList包含ObjectA对象按字段日期降序排序。我们正在检查列表成员是否与其前任成员的日期相同或相等。