cjstehno / ersatz

🤖 A simulated HTTP server for testing client code with configurable responses.
https://cjstehno.github.io/ersatz
Apache License 2.0
47 stars 5 forks source link

Using variables in expectations block does not work #117

Closed KrzysztofKowalczyk closed 5 years ago

KrzysztofKowalczyk commented 5 years ago

In the following example first test case fails but second passes.

The only difference is that first one is using global variable where the second one is using local variable:


import com.stehno.ersatz.ErsatzServer
import spock.lang.AutoCleanup
import spock.lang.Specification

class FailedSpec extends Specification {

    @AutoCleanup ErsatzServer server = new ErsatzServer()

    String someValue = "World"

    def "does not work"() {
        given:
        server.expectations {
            get("/") {
                called(1)

                responder {
                    body("Hello $someValue")
                }
            }
        }

        when:
        def response = new URL(server.httpUrl).text

        then:
        response == "Hello World"
    }

    def "work"() {
        given:
        def someValue = "World"
        server.expectations {
            get("/") {
                called(1)

                responder {
                    body("Hello $someValue")
                }
            }
        }

        when:
        def response = new URL(server.httpUrl).text

        then:
        response == "Hello World"
    }
}

This is most likely caused by this line: https://github.com/cjstehno/ersatz/blob/master/src/main/groovy/com/stehno/ersatz/Expectations.groovy#L98

get(String) has special meaning in groovy as any unknown field would delegate resolution to this method to get a value. Together with DELEGATE_FIRST strategy it most likely calls this method instead of getting value from the owner.

Hence in general avoid implementing get(String) methods in groovy.

If that's the problem, it has very simple fix, just change method signature to :

Request get(CharSequence path)

It will not break clients as String is a CharSequence but it would stop the issues.

cjstehno commented 5 years ago

Thanks for the clear discussion of the issue. This is the same as the underlying issue in #110 - I like your CharSequence idea better than the method name change idea from the other ticket (e.g. GET).

You are welcome to create a patch to address the issue, otherwise it will wait for v2.0.

KrzysztofKowalczyk commented 5 years ago

I see that it actually works fine since 1.9.0

KrzysztofKowalczyk commented 5 years ago

I've still created #118

cjstehno commented 5 years ago

Ah, I guess I forgot to ask my stock question of "what version are you using" :-) Thanks for the fix. I will take a look at it this week and get a release out.

KrzysztofKowalczyk commented 5 years ago

I was pretty sure we are on latest version and we were, just in different project ;)

KrzysztofKowalczyk commented 5 years ago

Fixed in 1.9.0

radarsh commented 4 years ago

Stumbled up on this today. Using ersatz 1.9.0:safe@jar, Groovy 2.5.13 and the below syntax fails:

server.expectations {
    get("/some-url/${someVariable}") {
        ...
    }
}

Currently working around by inlining the variable someVariable in all my expectations.

cjstehno commented 4 years ago

Fails how? Please try it in 2.0.0 - if you still have the issue, please create a new issue with as much detail as possible including a failing test case or example code.

radarsh commented 4 years ago

It tries to use a URL of /some-url/Expectation and therefore none of my expectations are met. I cannot upgrade to 2.x immediately, but I know the new upper case method names in 2.x addresses it. I'll create a new issue for this.

cjstehno commented 4 years ago

I won't be making any bug fixes in the 1.9 line.

radarsh commented 4 years ago

That's fine. It's not a major problem now. I'll prioritise upgrading to 2.x in our next internal milestone.