I am trying to test for the results of certain exceptions when Nest has a value in IGetResponse.OriginalException
property.
I first set up the response:
var response = A.Fake<Nest.IGetResponse<Dictionary<string, object>>>();
A.CallTo(() => response.OriginalException).Returns(new Exception("Status code 404"));
Then the fake elastic client:
var client = A.Fake<Nest.IElasticClient>();
A.CallTo(client)
.WithReturnType<Nest.IGetResponse<Dictionary<string, object>>>()
.Returns(response);
The client gets injected into the class I am testing.
However, when stepping through the code, when the client is called it returns a faked response, but the OriginalException
getter has no value. Its not null, but none of the properties has any value. I was expecting the OriginalException.Message
to equal Status code 404.
I also tried setting the response object to:
var response = A.Fake<Nest.IGetResponse<Dictionary<string, object>>>();
A.CallTo(() => response.OriginalException.Message).Returns("Status code 404");
... with equally poor results.
How can I set the IGetResponse
so I can evaluate OriginalException.Message
in the class being tested?
More code was requested. I can show the entire test, and I will show the method being tested. Here is my entire test:
[TestMethod]
[ExpectedException(typeof(NotFoundException))]
public void Get_ClientReturns404_ThrowsNotFoundException()
{
// setup
var request = new DataGetRequest
{
CollectionName = string.Empty,
DocumentType = string.Empty,
DataAccessType = string.Empty
};
var response = A.Fake<Nest.IGetResponse<Dictionary<string, object>>>();
A.CallTo(() => response.OriginalException.Message).Returns("Status code 404");
var client = A.Fake<Nest.IElasticClient>();
A.CallTo(client)
.WithReturnType<Nest.IGetResponse<Dictionary<string, object>>>()
.Returns(response);
var elasticSearch = new ElasticSearch(null, client);
// test
var result = elasticSearch.Get(request);
// assert
Assert.Fail("Should have hit an exception.");
}
}
And here is the method being tested:
public async Task<Dictionary<string, object>> Get(DataGetRequest getRequest)
{
GetRequest request = new GetRequest(getRequest.CollectionName, getRequest.DocumentType, getRequest.Id);
var response = await Client.GetAsync<Dictionary<string, object>>(request);
if (response.OriginalException != null)
{
var message = response.OriginalException.Message;
if (message.Contains("Status code 404"))
throw new NotFoundException(String.Format("Not Found for id {0}", getRequest.Id));
else
throw new Exception(message);
}
return response.Source;
}
The error handling in the IF block is not very robust. Once the unit test works then the code will likely receive more love.
The return type of the mocked client is wrong as the IElasticClient.GetAsync<>
returns a Task<IGetResponse<T>>
.
Task<IGetResponse<T>> GetAsync<T>(IGetRequest request, CancellationToken cancellationToken = default(CancellationToken)) where T : class;
So the setup needs to return a Task
derived result to allow the async code
var response = await Client.GetAsync<Dictionary<string, object>>(request);
to flow as expected.
For example
[TestMethod]
[ExpectedException(typeof(NotFoundException))]
public async Task Get_ClientReturns404_ThrowsNotFoundException() {
//Arrange
var originalException = new Exception("Status code 404");
var response = A.Fake<Nest.IGetResponse<Dictionary<string, object>>>();
A.CallTo(() => response.OriginalException).Returns(originalException);
var client = A.Fake<Nest.IElasticClient>();
A.CallTo(() =>
client.GetAsync<Dictionary<string, object>>(A<IGetRequest>._, A<CancellationToken>._)
).Returns(Task.FromResult(response));
var request = new DataGetRequest {
CollectionName = string.Empty,
DocumentType = string.Empty,
DataAccessType = string.Empty
};
var elasticSearch = new ElasticSearch(null, client);
// Act
var result = await elasticSearch.Get(request);
// Assert
Assert.Fail("Should have hit an exception.");
}