Consider a test below:
#Unroll
def 'demo test'() {
expect:
methodTest(inp) == res
where:
inp || res
"a" || true
"b" || false
}
This test may result:
demo test[0]
demo test[1]
My question, is there any way to get those iteration index during test execution? More clearly, while the first test is executing then I would like to get the index 0 in expect: or when: block?
Not sure when and how Spock actually assigns those iteration indexes.
My understanding of the where clause is that spock doesn't iterate over the options in where, it creates a separate test for each one.
It seems that you can't infer an iteration number from Spock. As Deon mentioned, Spock creates different specifications based on your where block.
It your really need to know an index you can write it explicitly in the where block:
where:
idx | inp || res
0 | "a" || true
1 | "b" || false
If you just want to know your actual arguments you can include them into the method name:
#Unroll
def "demo test: result should be #res if inp=#inp"() {
expect:
methodTest(inp) == res
where:
inp || res
"a" || true
"b" || false
}
Related
Let's say deleteInvocation=1, notDeletedInvocation=2
Does that mean I will have 3 records in the Post array before entering?
3 * postConverter.apply(Post, null) >> PostPayload
#Unroll
def "Verify PostCoreImpl.findById return Post when includeRemoved: [#includeRemoved]"() {
setup:
def PostId = UUID.randomUUID()
def Post = Mock(Post)
def PostPayload = Mock(PostPayload)
when:
def actual = underTest.findPostById(PostId, includeRemoved, false, false)
then:
deleteInvocation * mockPostDataManager.findByIdincludeRemoved(PostId) >> Post
notDeletedInvocation * mockPostDataManager.findById(PostId) >> Post
3 * postConverter.apply(Post, null) >> PostPayload
actual == PostPayload
where:
deleteInvocation | notDeletedInvocation | includeRemoved
1 | 0 | true
0 | 1 | false
}
First of all, I would advise against using variable names starting with capital letters, especially if these variables are identical with actual class names(!). For example, I would change
def PostId = UUID.randomUUID()
def Post = Mock(Post)
def PostPayload = Mock(PostPayload)
to
def postId = UUID.randomUUID()
def post = Mock(Post)
def postPayload = Mock(PostPayload)
and update all places where these variables are used.
As for your question, the notation integerNumber * methodCall(...) on a mock or spy object means that you want to verify that methodCall(...) was called exactly integerNumber times during your test (interaction checking).
Please consult the Spock manual chapter "Interactions" for further information.
The notation integerNumber * methodCall(...) >> stubResult means that you combine interactions with stubbing, i.e. specify two things at once with a mock or spy object.
Please consult the Spock manual chapter "Combining Mocking and Stubbing" for further information.
I have a function which I'm trying to test
##described_class.expects(:foo).with(
1,
2,
<any number>
)
##described_class.bar()
so here my function bar calls foo. Is there a way to set this up where :foo's third parameter can be any number?
From the question title and the code snipped I'm assuming you're using this version of mocha.
If that's the case then you can pass a block to your with and define your expectations in there, see the docs here.
object = mock()
object.expects(:expected_method).with() { |value| value % 4 == 0 }
object.expected_method(16)
# => verify succeeds
object = mock()
object.expects(:expected_method).with() { |value| value % 4 == 0 }
object.expected_method(17)
# => verify fails
The documentation doesn't have an example with more than one parameter as input, but given Ruby's nature I'd assume something like this would work
##described_class.expects(:foo).with { |first, second, third| first == 1 && second == 2 }
I'm expecting 9, but getting nil. Not sure why.
> dfs = p.disk_items.inject { |acc, di| acc + 1 if di.type == "DiskFile" }
=> nil
The same problem:
> dfs = p.disk_items.inject(0) { |acc, di| if di.type == "DiskFile" then acc + 1 end }
=> nil
Clearly there are nine occurrences where di.type == "DiskFile" is true:
> dfs = p.disk_items.inject(0) { |acc, di| puts di.type == "DiskFile" }
true
true
true
true
true
true
true
true
true
false
=> nil
What am I screwing up? If I can't use conditionals, then maybe there's a better way to count all the ActiveRecord objects in an array that satisfies a condition on an attribute.
Edit: FWIW:
> p.disk_items.class
=> ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_DiskItem
looks like this implementation in Rails source of count may not accept blocks? Though I may be reading this wrong or looking in the wrong place...
user2246674 is correct, the if statement is returning nil, but inject should always return acc You can use a turnery operator to make this easy
dfs = p.disk_items.inject(0) { |acc, di| di.type == "DiskFile" ? acc + 1 : acc }
When the if "doesn't run" the block evalutates to nil. This happens on the last case and the result (nil) is returned.
Consider (the long-hand):
if di.type == "DiskFile" then
acc + 1
else
acc # so we never return nil
end
While there are various short-hands (i.e. ?:), I would use a count {block}. If needing to do something else with the values (perhaps still using in an inject "sometimes"), select might also be useful.
p.disk_items.count {|di| di.type == "DiskFile"}
I need to perform a null or empty check on a collection; I think that !members?.empty is incorrect. Is there a groovier way to write the following?
if (members && !members.empty) {
// Some Work
}
There is indeed a Groovier Way.
if (members) {
//Some work
}
does everything if members is a collection. Null check as well as empty check (Empty collections are coerced to false). Hail Groovy Truth. :)
FYI this kind of code works (you can find it ugly, it is your right :) ) :
def list = null
list.each { println it }
soSomething()
In other words, this code has null/empty checks both useless:
if (members && !members.empty) {
members.each { doAnotherThing it }
}
def doAnotherThing(def member) {
// Some work
}
!members.find()
I think now the best way to solve this issue is code above. It works since Groovy 1.8.1 http://docs.groovy-lang.org/docs/next/html/groovy-jdk/java/util/Collection.html#find(). Examples:
def lst1 = []
assert !lst1.find()
def lst2 = [null]
assert !lst2.find()
def lst3 = [null,2,null]
assert lst3.find()
def lst4 = [null,null,null]
assert !lst4.find()
def lst5 = [null, 0, 0.0, false, '', [], 42, 43]
assert lst5.find() == 42
def lst6 = null;
assert !lst6.find()
I can't quite figure out what I'm doing wrong here..
if #calc.docket_num =~ /DC-000044-10/ || #calc.docket_num =~ /DC-67-09/
#calc.lda = true
else
#calc.lda = false
end
But it seems that #calc.docket_num can be any string whatsoever and it always returns as true.
Am I not doing this right?
This is a one-liner:
#calc.lda = !!(#calc.docket_num =~ /DC-000044-10|DC-67-09/)
The !! forces the response to true/false, then you can assign your boolean variable directly.
Alternatively you could use the triple equals (===) operator for the Regexp class which is used for determining equality when using case syntax.
#calc.lda = /DC-000044-10|DC-67-09/ === #calc.docket_num
#calc.lda
=> true
BEWARE
/Regexp/ === String is totally different than String === /Regexp/!!!! The method is not commutative. Each class implements === differently. For the question above, the regular expression has to be to the left of ===.
For the Regexp implementation, you can see more documentation on this (as of Ruby 2.2.1) here.
I think the issue is somewhere else in your implementation. Use this code to check it:
k = 'random information'
if k =~ /DC-000044-10/ || k =~ /DC-67-09/
puts 'success'
else
puts 'failure'
end
=> failure