0

I'm trying to iterate through each status to check if the ArrayList has at least 1 ACTIVE and 1 INACTIVE status.

var active = false;
var inactive = false;
for (item <- reasons.items) {
  if(item.status == "ACTIVE")
    active = true
  if(item.status == "INACTIVE")
    }
active must be (true)
inactive must be (true)

Is there a cleaner way to do this? I've tried with streams like this but no luck

var active = false;      
var stream = reasons.items.toStream
        .forEach(item => if(item.status == "ACTIVE") {active = true})

Note: reasons holds items (There is 1 items). items holds individual items that can be called like reasons.items.get(x).

Taariq
  • 61
  • 8

3 Answers3

1

The clean approach would be

val active = reasons.items.exists(item => item.status == "ACTIVE")

or shorter

val active = reasons.items.exists(_.status == "ACTIVE")

Similarly for val inactive. This does have the problem of iterating through the list twice (but stopping once a suitable item is found both times unlike in your code).

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
1

For "at least 1" you can use exists on items which checks the predicate given and returns true if at least one of the items satisfies the criteria. For "ACTIVE and INACTIVE" you can combine two exists calls for an inefficient approach using &&.

reasons.items.exists(_.status.equals("ACTIVE")) && reasons.items.exists(_.status.equals("INACTIVE"))`
Brian
  • 20,195
  • 6
  • 34
  • 55
1

The other answers explain well how to achieve this using Scala collections. Since it looks like you're using ScalaTest, I wanted to add that you could also use ScalaTest to loop over the elements.

Using the loop-style syntax from inspectors:

forAtLeast(1, reasons.items) { item =>
  item.status must be ("ACTIVE")
}

forAtLeast(1, reasons.items) { item =>
  item.status must be ("INACTIVE")
}

Note that inspectors are defined separately from matchers, so you'll have to import org.scalatest.Inspectors._ or extends … with org.scalatest.Inspectors to get forAtLeast into scope.

If you want to avoid the loop-style syntax from inspectors, you can use the inspector shorthand syntax together with the reflection-based have syntax:

atLeast(1, reasons.items) must have ('status "ACTIVE")
atLeast(1, reasons.items) must have ('status "INACTIVE")

If you want to avoid the reflection-based syntax for have, you can extend the have syntax to support your status property directly:

def status(expectedValue: String) =
  new HavePropertyMatcher[Item, String] {
    def apply(item: Item) =
      HavePropertyMatchResult(
        item.status == expectedValue,
        "status",
        expectedValue,
        item.title
      )
  }

atLeast(1, reasons.items) must have (status "ACTIVE")
atLeast(1, reasons.items) must have (status "INACTIVE")

Or if you prefer be over have, you could extend the be syntax to add support for active and inactive:

class StatusMatcher(expectedValue: String) extends BeMatcher[Item] {
  def apply(left: Item) =
    MatchResult(
      left.status == expectedValue,
      left.toString + " did not have status " + expectedValue,
      left.toString + " had status " + expectedValue,
    )
}

val active = new StatusMatcher("ACTIVE")
val inactive = new statusMatcher("INACTIVE")

atLeast(1, reasons.items) must be (active)
atLeast(1, reasons.items) must be (inactive)

In the examples here it looks a bit silly to define your own matchers just to save a couple of words in an assertion, but if you write hundreds of tests about the same properties, it can be really convenient to get your assertions down to one line and still be naturally readable. So in my experience, defining your own matchers like this can make sense if you reuse them in a lot of tests.

Toxaris
  • 7,156
  • 1
  • 21
  • 37
  • I like your answer but I don't believe we are using ScalaTest so I can't do . forAtLeast. – Taariq Dec 07 '18 at 15:38
  • For forAtLeast, what scalatest packages need to be imported? – Taariq Dec 11 '18 at 15:16
  • `import org.scalatest.Inspectors._` or `class MySpec extends ... with org.scalatest.Inspectors` should work, see http://doc.scalatest.org/3.0.1/#org.scalatest.Inspectors. I also added this to the answer. – Toxaris Dec 11 '18 at 21:18