-2

I work with unit-tests and encounter this problem: I have some classes and each have their own isEqual() method. At some point I came to a situation where an unit-test sometimes fails and sometimes succeeds.

I check the equality of two objects that contain a set of objects. Here the the problem arises. Sometimes the test "obj1.mySet == obj2.mySet" fails - sometimes not. I test this with only one object in each set (mySet). The test for the equality of this objects (in mySet) itself succeeds.

I tried some hours to find a mistake in my code, but couldn't find any. Now I have a workaround that helps to pass the test, but I do not understand, what's going on. I have a method within the test-objects, that returns the objects of the set as an (ordered) array. When I test the equality of this arrays, the test always succeeds.

Do someone know, what’s going on?

Update:

In my BaseClass

func hash(into hasher: inout Hasher) { hasher.combine(firebaseID) }
static func == (lhs: FirebaseObject, rhs: FirebaseObject) -> Bool { return lhs.isEqual(to: rhs) }
func isEqual(to object: Any?) -> Bool {
        guard object != nil && object is FirebaseObject else { return false }
        let value = object as! FirebaseObject
        return firebaseID == value.firebaseID && name == value.name
    }

In the SubClass

override func isEqual(to object: Any?) -> Bool {
        guard object != nil && object! is MealPlanned else { return false }
        let obj = object as! MealPlanned

        var result = ""
        if !super.isEqual(to:obj)           { result.append("fbObject ") }
        if portions != obj.portions         { result.append("portions ") }
        if imgID != obj.imgID               { result.append("imgID ") }
        if meal != obj.meal                 { result.append("meal ") }
        if date != obj.date                 { result.append("date ") }
        if portionsInBaseMeal != obj.portionsInBaseMeal             {result.append("portionsInBaseMeal ") }
        if getIngrediencesInMeals() != obj.getIngrediencesInMeals() { result.append("ingrediencesInMeals ") }


        if result.count > 0 {
            if (showsDifference) { print("difference in MealPlanned <\(obj.name ?? "Fehler")>: \(result)") }
            return false
        }
        return true
    }

I did it this way, to find and print the problem.

This version succeeds.

if getIngrediencesInMeals() != obj.getIngrediencesInMeals() { result.append("ingrediencesInMeals ") 

getIngrediencesInMeals() returns the set as an ordered array.

In this way the test sometimes succeeds sometimes fails:

if ingrediences != ingrediences { result.append("ingrediencesInMeals ") 

This returns the ordered array:

func getIngrediencesInMeals() -> [IngredienceInMeals]   { return ingrediences.sorted{ $0.position < $1.position } }

in IngredienceInMeals

override func isEqual(to object: Any?) -> Bool {
        guard object != nil && object! is IngredienceInMeals else { return false }
        let obj = object as! IngredienceInMeals

        var result = ""
        if !super.isEqual(to:obj)           { result.append("fbObject ")}
        if unit != obj.unit                 { result.append("unit ")}
        if quantity != obj.quantity         { result.append("quantity ")}
        if ingredience != obj.ingredience   { result.append("ingredience ")}
        if position != obj.position         { result.append("position ")}
        if result.count > 0 {
            if (showsDifference) { print("difference in IngredienceInMeal <\(obj.name ?? "Fehler")>: \(result)") }
            return false
        }
        return true
    }
E_net4
  • 27,810
  • 13
  • 101
  • 139
M.P.
  • 1
  • 3

1 Answers1

0

if you want to compare two objects use Equatable protocol method in your object class

example of compare two objects

    class ItemModel : Equatable {

    var TypeOfOffer : String?
    var TypeOfSelling : String?
    var Address : String?
    var NumberOfRoom : String?
    var Price : String?
    var Image : String?
    var ID : String?
    var itemId : String?


    init(TypeOfOffer : String? , TypeOfSelling : String?, Address : String?, NumberOfRoom : String? , Price : String?, Image : String?, ID : String?, itemId : String?  )
    {
        self.TypeOfOffer = TypeOfOffer
        self.TypeOfSelling = TypeOfSelling
        self.Address = Address
        self.NumberOfRoom = NumberOfRoom
        self.Price = Price
        self.Image = Image
        self.ID = ID
        self.itemId = itemId
    }

    static func == (lhs: ItemModel, rhs: ItemModel) -> Bool {
        var isIt = true
        isIt = (lhs.TypeOfOffer == "" || lhs.TypeOfOffer == rhs.TypeOfOffer)
        && (lhs.TypeOfSelling == "" || lhs.TypeOfSelling == rhs.TypeOfSelling)
        && (lhs.Address == "" || lhs.Address == rhs.Address)
        && (lhs.NumberOfRoom == "" || lhs.NumberOfRoom == rhs.NumberOfRoom)
        && (lhs.Price == "" || lhs.Price == rhs.Price)

        return isIt
    }



}

Compare two instances of an object in Swift!

RajeshKumar R
  • 15,445
  • 2
  • 38
  • 70
  • Without conforming to the Hashable protocol, it's not possible to have a set of objects of this class. – M.P. Apr 04 '19 at 08:43