Unit testing 模拟域对象不工作

Unit testing 模拟域对象不工作,unit-testing,grails,mocking,Unit Testing,Grails,Mocking,我是一个grails/groovy新手,所以请原谅我这个简单的问题,但我真的尝试了所有的方法,但没有成功。一般来说,我想为我的服务方法编写真正简单的单元测试。但是我不明白为什么我的mock没有列表 我的服务: class MenuService { def mailService def prepareMenu() { def newDinners = [] def soups = Dish.findAllWhere(dishKind: DishKind.SOUP)

我是一个grails/groovy新手,所以请原谅我这个简单的问题,但我真的尝试了所有的方法,但没有成功。一般来说,我想为我的服务方法编写真正简单的单元测试。但是我不明白为什么我的mock没有列表

我的服务:

class MenuService {

def mailService

def prepareMenu() {
    def newDinners = []
    def soups = Dish.findAllWhere(dishKind: DishKind.SOUP)
    def mainCourses = Dish.findAllWhere(dishKind: DishKind.MAIN_COURSE)
    def salads = Dish.findAllWhere(dishKind: DishKind.SALAD)
    def menu = checkIfMenuExists(Menu.last())

    deleteUsedMainCoursesAndSoups(menu, soups, mainCourses)
    deleteUsedSalads(menu, salads)

    Collections.shuffle(mainCourses)
    mainCourses = mainCourses.subList(0, 7);

    mainCourses.each {
        Dinner dinner = new Dinner()
        dinner.mainCourse = it
        if (it.withSoup) {
            Collections.shuffle(soups)
            dinner.soup = soups.get(0)
            soups.remove(0)
        }
        newDinners.add(dinner)
    }

    Collections.shuffle(salads)
    salads = salads.subList(0, 2)

    menu.dinners = newDinners
    menu.salads = salads

    menu.save()
    sendMenu(menu)
}

private void deleteUsedSalads(Menu menu, salads) {
    if (!menu.salads.isEmpty()) {
        menu.salads.each {
            if (salads.contains(it)) {
                salads.remove(it)
            }
        }
    }
}

private void deleteUsedMainCoursesAndSoups(Menu menu, soups, mainCourses) {
    if (!menu.dinners.isEmpty()) {
        menu.dinners.each {
            if (mainCourses.contains(it.mainCourse)) {
                mainCourses.remove(it)
            } else if (soups.contains(it.soup))
                soups.remove(it)
        }
    }
}

private Menu checkIfMenuExists(Menu menu) {
    if (menu == null) {
        menu = new Menu()
        menu.dinners = new ArrayList<Dinner>()
        menu.salads = new ArrayList<Dish>()
    }
    menu
}

def sendMenu(Menu menu) {
    mailService.sendMail {
        to ""
        subject ""
        body(view: "/mail", model: [dinners: menu.dinners, salads: menu.salads])
    }
}

}
当我运行测试时,我有一个失败:

Failure:  testIfItChoosesNewMenu(familyhelper.MenuServiceTests)
java.lang.IndexOutOfBoundsException: toIndex = 7
at java.util.SubList.<init>(AbstractList.java:602)
at java.util.RandomAccessSubList.<init>(AbstractList.java:758)
at java.util.AbstractList.subList(AbstractList.java:468)
at familyhelper.MenuService.prepareMenu(MenuService.groovy:18)
at familyhelper.MenuServiceTests.testIfItChoosesNewMenu(MenuServiceTests.groovy:51)

这些都是空的。我已经读到,当我添加@Mock注释时,域对象的所有动态函数都被注入,但即使这样也没有帮助。有人知道如何修正这个测试吗?提前谢谢

可能是你忘了保存盘子

def salads = [
            new Dish(name: "Salad 1", dishKind: DishKind.SALAD, ingredients: "").save(),
            new Dish(name: "Salad 2", dishKind: DishKind.SALAD, ingredients: "").save(),
            new Dish(name: "Salad 3", dishKind: DishKind.SALAD, ingredients: "").save(),
            new Dish(name: "Salad 4", dishKind: DishKind.SALAD, ingredients: "").save(),
    ]

可能是你忘了保存盘子

def salads = [
            new Dish(name: "Salad 1", dishKind: DishKind.SALAD, ingredients: "").save(),
            new Dish(name: "Salad 2", dishKind: DishKind.SALAD, ingredients: "").save(),
            new Dish(name: "Salad 3", dishKind: DishKind.SALAD, ingredients: "").save(),
            new Dish(name: "Salad 4", dishKind: DishKind.SALAD, ingredients: "").save(),
    ]

您不需要显式模拟域类@Mock应该为你做这件事

@TestFor(MenuService)
@Mock([Dish, Menu])
class MenuServiceTests {

    void testIfItChoosesNewMenu() {

        def soups = [
            new Dish(name: "Soup 1", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 2", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 3", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 4", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 5", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 6", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 7", dishKind: DishKind.SOUP, ingredients: "")
        ]

        def mainCourses = [
            new Dish(name: "Main course 1", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 2", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 3", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 4", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 5", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 6", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 7", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 8", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 9", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 10", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 11", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 12", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 13", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 14", dishKind: DishKind.MAIN_COURSE, ingredients: "")
        ]

        def salads = [
            new Dish(name: "Salad 1", dishKind: DishKind.SALAD, ingredients: ""),
            new Dish(name: "Salad 2", dishKind: DishKind.SALAD, ingredients: ""),
            new Dish(name: "Salad 3", dishKind: DishKind.SALAD, ingredients: ""),
            new Dish(name: "Salad 4", dishKind: DishKind.SALAD, ingredients: "")
        ]

        //Save the domain classes
        [soups, mainCourses, salads].each{it*.save(flush: true, failOnError: true)}

        //Note service is auto injected by @TestFor
        //SO no need to instantiate
        Menu menu = service.prepareMenu() 

        assertEquals 2, menu.salads.size()
        assertEquals 7, menu.dinners.size()
    }
} 

如果您还不了解插件,那么我建议您将其用于此类测试。总的来说,我还建议使用spock作为测试框架。

您不需要显式地模拟域类@Mock应该为你做这件事

@TestFor(MenuService)
@Mock([Dish, Menu])
class MenuServiceTests {

    void testIfItChoosesNewMenu() {

        def soups = [
            new Dish(name: "Soup 1", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 2", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 3", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 4", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 5", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 6", dishKind: DishKind.SOUP, ingredients: ""),
            new Dish(name: "Soup 7", dishKind: DishKind.SOUP, ingredients: "")
        ]

        def mainCourses = [
            new Dish(name: "Main course 1", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 2", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 3", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 4", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 5", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 6", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 7", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 8", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 9", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 10", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 11", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 12", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 13", dishKind: DishKind.MAIN_COURSE, ingredients: ""),
            new Dish(name: "Main course 14", dishKind: DishKind.MAIN_COURSE, ingredients: "")
        ]

        def salads = [
            new Dish(name: "Salad 1", dishKind: DishKind.SALAD, ingredients: ""),
            new Dish(name: "Salad 2", dishKind: DishKind.SALAD, ingredients: ""),
            new Dish(name: "Salad 3", dishKind: DishKind.SALAD, ingredients: ""),
            new Dish(name: "Salad 4", dishKind: DishKind.SALAD, ingredients: "")
        ]

        //Save the domain classes
        [soups, mainCourses, salads].each{it*.save(flush: true, failOnError: true)}

        //Note service is auto injected by @TestFor
        //SO no need to instantiate
        Menu menu = service.prepareMenu() 

        assertEquals 2, menu.salads.size()
        assertEquals 7, menu.dinners.size()
    }
} 

如果您还不了解插件,那么我建议您将其用于此类测试。作为一个整体,我还建议使用spock作为测试框架。

要在数据库中使用GORM找到一些东西,您需要先保存它@Alidad是对的,但您可能应该使用:

 new Dish(...).save(false)

false
save
中禁用域实体验证。

要使用GORM在DB中查找内容,需要先保存它@Alidad是对的,但您可能应该使用:

 new Dish(...).save(false)

false
save
中禁用域实体验证。

感谢您的建议,我将尝试查看此插件,我对Grails非常陌生。但我还是想知道我的测试出了什么问题。我尝试了你的更改,但我的测试仍然失败。你可以在我的问题中看到错误。它只是出站..例外,因为列表是空的,因为它们没有我的模拟数据。谢谢你的建议,我会尝试看看这个插件,我对Grails真的很陌生。但我还是想知道我的测试出了什么问题。我尝试了你的更改,但我的测试仍然失败。你可以在我的问题中看到错误。它只是出站..异常,因为列表是空的,因为它们没有我的模拟数据。