Hi and thanks in advance for any help. I'm working on a GraphQL project using async_graphql. I'd like to be able to mock services to make sure queries are testable.
Right now I expose a simple query like
struct ClientQueryRoot;
impl ClientQueryRoot {
pub fn client(&self, id: String) -> Client {
Client::new(id)
}
}
Where Client
is
#[derive(Debug)]
struct Client {
profile: Profile,
}
impl Client {
pub fn new(id: String) -> Self {
Self {
profile: RealClientService::get_client_profile(id),
}
}
}
The first step in mocking has been parametizing RealClientService
like
trait ClientService {
fn get_client_profile(id: String) -> Profile;
}
impl Client {
// When we create a client we pass in the type of the ClientService to use
// for retrieving the profile. This is our dependancy injection, but maybe
// it could be more aptly called "type injection"
pub fn new<CS: ClientService>(id: String) -> Self {
Self {
profile: CS::get_client_profile(id),
}
}
}
Which allows for creating a client like
let real_client = Client::new::<RealClientService>(ctx, "mock id".into());
// or
let mock_client = Client::new::<MockClientService>(ctx, "mock id".into());
To be able to test queries from the root I'd like to be able to parameterize types used throughout the entire query from the root. For example, I'd like to be able to
let query_root = ClientQueryRoot::new<MockClientService>();
let schema = Schema::new(query_root, EmptyMutation, EmptySubscription);
let res = schema.execute("{ client(id: "xyz") }").await;
// assert some things about the result...
I was attempting to do this like
struct ClientQueryRoot<CS: ClientService>;
impl<CS: ClientService> ClientQueryRoot<CS> {
type ClientService = CS;
pub fn client(&self, id: String) -> Client {
Client::new::<Self::ClientService>(id)
}
}
But I am getting the error associated types are not yet supported in inherent impls (see #8995)
and was hoping for some help on the right way to do this
Here is a link to a playground that demonstrates everything I'm taking about.