Mocking dry-validation schemas in Rails controller tests


#1

Hello! I’m using dry-validation to validate JSON payloads in my Rails API controller, a bit like this:

def create
  result = CreateUserSchema.call(member_params.to_hash)
  return result_as_json(result.errors) unless result.success?
  # create a user
end

I’ve got CreateUserSchema unit tested, so really I just want to mock CreateUserSchema and check that (for example) a 200 is returned when success? is true, and a 400 is returned when it is false. However, because it’s frozen, when I try to do this:

result = double('result', success?: true)
allow(CreateMemberSchema).to receive(:call) { result }

I get an error like this:

RuntimeError: can't modify frozen object

Is there any way around this?


#2

I personally never use mocks, most of the things are registered in a container where they can be easily stubbed in tests, see dry-container and its testing interface. You can put all your schemas there though I’m not a big fan of the approach where validation schemas live in container.


#3

You are better off having a factory for your object that will help you create valid objects and having the validation actually run.


#4

Just to clarify, CreateUserSchema is the name of the schema, rather than of a class that generates a schema. It’s a slightly odd name, but this schema is checking the format of some incoming JSON that creates a user, to see if it’s valid.

@flash-gordon: That makes sense. In this case however, I don’t want to test all the validation logic in my UserController: I just want to check it responds correctly when the schema is valid, and invalid. The actual validation is tested in the unit tests for my schema.