Mock IRequestClient<> during Integration Testing using MassTransit - .net-core

I'm trying to do integration testing against a MediatR Command whose handler depends on an IRequestClient injected into its constructor.
public class SayHelloCommand : IRequest<string>
{
}
public class SayHelloCommandHandler : IRequestHandler<SayHelloCommand, string>
{
private readonly IRequestClient<IGetProfileMessageResult> _profileClient;
public SayHelloCommandHandler(IRequestClient<IGetProfileMessageResult> profileClient)
{
_profileClient = profileClient;
}
public async Task<string> Handle(SayHelloCommand request, CancellationToken cancellationToken)
{
var profile = (await _profileClient.GetResponse<IGetProfileMessageResult>(new {ProfileId = 1})).Message;
return $"Hello {profile.FirstName}";
}
}
I've setup my test suite to use the InMemoryMassTransit but whenever I run my test it times out when it reaches the call using the IRequestClient<>. I've also tried to moq the IRequestClient to return a default response like this -
[Test]
public async Task ShouldSayHello()
{
var mockRequestClient = new Mock<IRequestClient<IGetProfileMessageResult>>();
mockRequestClient.Setup(x => x.GetResponse<IGetProfileMessageResult>(It.IsAny<Object>(), default, default)
.Result.Message).Returns(new GetProfileMessageResult
{
FirstName = "John"
});
serviceCollection.Add(new ServiceDescriptor(typeof(IRequestClient<IGetProfileMessageResult>), mockRequestClient.Object));
var result = await SendAsync(command);
result.Status.Should().BeFalse();
result.Message.Should().Contain("John");
}
but this still times out.
Is there a way I can set up the InMemoryMassTransit to return a default response when the requestclient is called?

You could use the in-memory test harness to setup a simple consumer that would respond to the request, instead of trying to mock IRequestClient. Though you should be able to mock it if you want, I just don’t know the syntax to properly configure your mock framework.
There are many samples using the test harness available, as well as all of the MassTransit unit tests.

Related

Using Akka.net with Asp.net on a Modular Monolith architecture

Iwould like to implement a rest service using Akka and Asp.net.
Following the example here
I create my AkkaService containing the FooActor ref and a controller who transform the http request to a RunProcess message which is sent to the FooActor.
[Route("api/[controller]")]
[ApiController]
public class MyController : Controller
{
private readonly ILogger<MyController> _logger;
private readonly IAkkaService Service;
public RebalancingController(ILogger<MyController> logger, IAkkaService bridge)
{
_logger = logger;
Service = bridge;
}
[HttpGet]
public async Task<ProcessTerminated> Get()
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
return await Service.RunProcess(cts.Token);
}
}
public class AkkaService : IAkkaService, IHostedService
{
private ActorSystem ActorSystem { get; set; }
public IActorRef FooActor { get; private set; }
private readonly IServiceProvider ServiceProvider;
public AkkaService(IServiceProvider sp)
{
ServiceProvider = sp;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
var hocon = ConfigurationFactory.ParseString(await File.ReadAllTextAsync("app.conf", cancellationToken));
var bootstrap = BootstrapSetup.Create().WithConfig(hocon);
var di = DependencyResolverSetup.Create(ServiceProvider);
var actorSystemSetup = bootstrap.And(di);
ActorSystem = ActorSystem.Create("AkkaSandbox", actorSystemSetup);
// </AkkaServiceSetup>
// <ServiceProviderFor>
// props created via IServiceProvider dependency injection
var fooProps = DependencyResolver.For(ActorSystem).Props<FooActor>();
FooActor = ActorSystem.ActorOf(rebalProps.WithRouter(FromConfig.Instance), "foo");
// </ServiceProviderFor>
await Task.CompletedTask;
}
public async Task<ProcessTerminated> RunProcess(CancellationToken token)
{
return await FooActor.Ask<ProcessTerminated>(new RunProcess(), token);
}
public FooActor(IServiceProvider sp)
{
_scope = sp.CreateScope();
Receive<RunProcess>(x =>
{
var basketActor = Context.ActorOf(Props.Create<BarActor>(sp), "BarActor");
basketActor.Tell(new BarRequest());
_log.Info($"Sending a request to Bar Actor ");
});
Receive<BarResponse>(x =>
{
...... Here I need to send back a ProcessTerminated message to the controller
});
}
Now, let's imagine the FooActor send a message to the BarActor telling him to perform a given task and wait the BarResponse. How could I send back the ProcessTerminated message to the controller?
Few points to take into considerations:
I want to ensure no coupling between BarActor and FooActor.
By example, I could add the original sender ActorRef to the BarRequest and
BarResponse. But the BarActor musn't know about the fooActor and
MyController. The structure of the messages an how the barActor
respond should not be dependent of what the FooActor do with the
BarResponse.
In the example I only use BarActor, but we can imagine to have many different actors
exchanging messages before returning the final result to the controller.
Nitpick: you should use Akka.Hosting and avoid creating this mock wrapper service around the ActorSystem. That will allow you to pass in the ActorRegistry directly into your controller, which you can use to then access FooActor without the need for additional boilerplate. See "Introduction to Akka.Hosting - HOCONless, "Pit of Success" Akka.NET Runtime and Configuration" video for a fuller explanation.
Next: to send the ProcessTerminated message back to your controller you need to save the Sender (the IActorRef that points to the temporary actor created by Ask<T>, in this instance) during your Receive<RunProcess> and make sure that this value is available inside your Receive<BarResponse>.
The simple ways to accomplish that:
Store the Sender in a field on the FooActor, use behavior-switching while you wait for the BarActor to respond, and then revert back to your original behavior.
Build a Dictionary<RunProcess, IActorRef> (the key should probably actually be some unique ID shared by RunProcess and BarResponse - a "correlation id") and reply to the corresponding IActorRef stored in the dictionary when BarResponse is received. Remove the entry after processing.
Propagate the Sender in the BarRequest and BarResponse message payloads themselves.
All three of those would work. If I thought there were going to be a large number of RunProcess requests running in parallel I'd opt for option 2.
Another way of doing it is by simply forwarding the next message to the next actor. The Tell operation have a second parameter that can be used to override the message sender. If you're sure that all path has to respond back to the original Ask inside the Http controller, you can do this inside the FooActor:
Receive<RunProcess>(x =>
{
var basketActor = Context.ActorOf(Props.Create<BarActor>(sp), "BarActor");
basketActor.Tell(new BarRequest(), Sender);
_log.Info($"Sending a request to Bar Actor ");
});
This way, the original Ask actor is considered as the sender of the new BarRequest message instead of the FooActor, and if BarActor decide to reply by doing a Sender.Tell(new ProcessTerminated()). the ProcessTerminated message will be sent to the Http controller.

How to convert to Xunit using mocking

I have these two methods in my service class
public class PatientService : IPatientService
{
private readonly IRestClient _restClient;
private readonly IAppSettings _appSettings;
public PatientService(IRestClient restClient, IAppSettings appSettings)
{
_restClient = restClient;
_appSettings = appSettings;
}
public async Task<IList<PatientViewModel>> GetPatients(int wardId)
{
var url = _appSettings.Server + _appSettings.PatientServiceEndPoint + wardId;
var token = _appSettings.Token;
return GetPatientList(await _restClient.GetAsync<List<PatientInfo>>(url, token));
}
public IList<PatientViewModel> GetPatientList(IList<PatientInfo> patientInfoList)
{
return patientInfoList.Select(p => new PatientViewModel(p)).ToList();
}
}
I need to add this code to my Xunit.cs. How to do it?
I've implemented this and I do not know how to proceed.
private readonly PatientListPageViewModel _patientListPageViewModel;
private readonly Mock<IPatientService> _patient;
public PatientServiceTests()
{
_patient = new Mock<IPatientService>();
_patientListPageViewModel = new PatientListPageViewModel(_patient.Object);
}
[Fact]
public void GetListByWard_PassingWardId_GetPatientsCountAccordingToWardId()
{
}
This is what I tried to do. How to convert those two methods in service to be testable?
You did get mocking a bit wrong. It is not the component under test that is mocked, but its dependencies. When unit-testing you'd like to test a unit in isolation. Your case of mocking would be kind of correct if you unit-tested the PatientListPageViewModel, but since your test class is named PatientServiceTests I assume that you really wanted to test PatientService. If you wanted to test the former, you would be quite right to mock IPatientService, but when testing PatientService, IRestClient and IAppSettings shall be mocked
public PatientServiceTests()
{
_restClientMock = new Mock<IRestClient>();
_appSettingsMock = new Mock<IAppSettings>();
_patientService = new PatientService(_restClientMock.Object, _appSettingsMock.Object);
}
And your test could be something like
[Fact]
public async Task ReturnsCorrectPatientList() // async supported as of xUnit 1.9
{
// set up the mock
_restClientMock.SetUp(restClient => restClient.GetAsync<List<Patient>>(It.IsAny<string>(), It.IsAny<string>())
.Returns(() => Task.FromResult(/* what patients it shall return */));
var result = await _patientService.GetPatients(0);
// compare whether the returned result matches your expectations
}
If you wanted to test whether the URL is formed correctly, you could use Verify
[Theory]
[InlineData("SERVER", "ENDPOINT", 12, "1234", "SERVERENDPOINT12")]
[InlineData("https://localhost:65000", "/patients/", 5, https://localhost:65000/patients/5")]
public void TestWhetherCorrectUrlIsCalled(string server, string endpoint, int wardId, string token, string expectedUrl)
{
_appSettingsMock.SetupGet(appSettings => appSettings.Server).Returns(server);
_appSettingsMock.SetupGet(appSettings => appSettings.PatientServiceEndPoint).Returns(endpoint);
_appSettingsMock.SetupGet(appSettings => appSettings.Token).Returns(token);
_restClientMock.SetUp(restClient => restClient.GetAsync<List<Patient>>(It.IsAny<string>(), It.IsAny<string>())
.Returns(() => Task.FromResult(new List<Patient>()));
// we do not need the result
await _patientService.GetPatients(wardId);
_restClientMock.Verify(restClient => restClient.GetAsync<List<Patient>>(exptectedUrl, token), Times.Once);
}
We are setting up the IRestClient in this case, since it would return null otherwise. And await null would cause your test to fail. After GetPatients has been called we are using Verify to verify that GetAsync has been called with the correct parameters. If it has not been called, Verify will throw and your test will fail. Times.Once means, that GetAsync shall have been called once and only once.
On a side note: Viewmodels shall have a meaning in the context of your user interface only. Services shall be independent and hence not return viewmodels, as you did, but POCOs (or maybe domain models). In this case the interface of your service should be
public interface IPatientService
{
public async Task<IList<Patient>> GetPatients(int wardId);
// ...
}

Handle on db not released during unit test global setup

I'm using NUnit 3 to do a global setup, which creates a local database needed to run several of my service tests, which looks like this:
[SetUpFixture]
public class FixtureSetup
{
private MobileServiceClient _client;
private SyncService _syncService;
[OneTimeSetUp]
public void GlobalSetup()
{
_client = Substitute.For<MobileServiceClient>(Settings.SyncUrl);
_syncService = Substitute.For<SyncService>(_client);
}
[OneTimeTearDown]
public void GlobalTeardown()
{
_syncService = null;
_client.Dispose();
}
}
Settings.SyncUrl contains the URL to Azure to which the Azure App Services SDK will by syncing eventually, and is not relevant to this question.
The one-time setup, simply constructs a new instance of the MobileServiceClient and passes that instance to my SyncService class, to construct the local store, which looks like this:
public class SyncService : ISyncService
{
private readonly IMobileServiceClient _client;
private MobileServiceSQLiteStore Store { get; }
public SyncService(IMobileServiceClient client)
{
_client = client;
Store = new MobileServiceSQLiteStore(Settings.SyncDb);
Store.DefineTable<User>();
_client.SyncContext.InitializeAsync(Store);
}
public async Task<List<TTable>> All<TTable>()
{
var table = await _client.GetSyncTable<TTable>().ToListAsync();
return table;
}
public async Task<TTable> Insert<TTable>(TTable table)
{
await _client.GetSyncTable<TTable>().InsertAsync(table);
return table;
}
public async Task<List<TTable>> Search<TTable>(Expression<Func<TTable, bool>> predicate)
{
var table = await _client.GetSyncTable<TTable>().Where(predicate).ToListAsync();
return table;
}
}
Settings.SyncDb simply points to the name of the db, called localstorage.db, and if on a mobile device, will store this in the application's file repository, on Windows or Mac, it will store it under the user's profile folder. Adding this just for reference.
My problem is that the global setup creates the localstorage.db correctly, but by the time the unit test runs, it cannot access the localstorage.db, because it's seemingly still in use by the global setup method.
I thought that reinstantiating the MobileServiceClient in the test class would resolve this, but it does not seem to do so. Is there a way that I can release the handle on the db, before hitting the unit test?
This is not an issue in development, as I can run the unit tests again after the first fail, but VSTS builds fail the test due to this reason.
Thanks in advance.

Moq, setup a Stub and Expected result

I am creating a mock and a stub.
The stub is the following contract:
public interface IMailService
{
void SetCredentials(ICredentials credentials);
bool Connect();
}
My assert is the following:
"Passing the right credentials to IMailService, will connect succesfully".
So I have created my mock object:
var mockAdapter = new Mock<IMailService>();
Now I should prepare this adapter. If the SetCredentials method is called using the right credentials, then the Connect() method should return true. Otherwise it will return false.
I am just not sure how I can setup this behavior using Moq.
You need 2 tests to cover this, one in which Connect returns true and one in which it returns false.
[Fact] // or [Test] depending on your testing framework
public void MailServiceConnectsIfCredentialsAreValid()
{
var mockMailService = new Mock<IMailService>();
mockMailService.Setup(x => x.Connect()).Returns(true);
// The rest of your code which will use the mockMailService.Object...
}
[Fact]
public void MailServiceFailsToConnectIfCredentialsAreInvalid()
{
var mockMailService = new Mock<IMailService>();
mockMailService.Setup(x => x.Connect()).Returns(false);
// The rest of your code which will use the mockMailService.Object...
}
For the purpose of your test, you do not care what ICredentials are passed. You are just covering the 2 possibilities of IMailService.Connect() which are it returns true or false. The actual logic for determining which will happen will exist in your tests for the actual implementation of IMailService.
You could also potentially scrap the SetCredentials method and just pass the ICredentials to Connect.
bool Connect(ICredentials credentials);

Unit testing http handlers?

My current project based in Asp .net makes considerable use of Http handlers to process various requests? So, is there any way by which I can test the functionality of each of the handlers using unit test cases? We are using Nunit and Moq framework to facilitate unit testing.
I think these blog entries from a while back are relevant:
http://www.kongsli.net/nblog/2009/05/03/aspnet-35-improving-testability-with-systemwebabstractions/
http://www.kongsli.net/nblog/2009/05/28/testability-with-systemwebabstractions-and-no-mock-framework/
See example #2 in the first post for an example on how to unit test an HttpHandler.
If you dont care about unit tests and want something quick and dirty you can use Fiddler
if you want a more integrated approach (Unit testing) you can use the WebRequest and WebResponse.
You sure can, although I haven't done myself "in anger".
Use a System.Net.WebClient to make HTTP calls against your handlers, and evaluate what comes back, that will allow you to test the public facing interface of the handler.
In this example I've hard-coded my target, and I'm using a method on the WebClient that will return a string.
The WebClient also gives you access to the ResponseHeaders, Encoding and other useful 'webby' stuff; you can also upload info as well.
using System.Net;
namespace UnitTestHttpHandler
{
public class TestHarness
{
public static string GetString()
{
WebClient myWebClient = new WebClient();
return myWebClient.DownloadString("http://localhost/Morphfolia.Web/ContentList.ashx");
}
}
}
You can then use the TestHarness to call the target HttpHandler and verify the results in your tests (or use a better approach to your testing if you know one - I'm not a unit testing guru).
[TestMethod]
public void TestMethod1()
{
string x = UnitTestHttpHandler.TestHarness.GetString();
Assert.IsTrue(x.Length > 5);
}
The default interface for IHttpHandler is not testable because the param for ProcessRequest(HttpContext context) is not mockable.
This answer is inspired by this post.
To make your IHttpHandler implementation testable you must first make a small change so we can use the mockable HttpContextBase:
From:
class YourHttpHandler : IHttpHandler
{
public bool IsReusable => true;
public void ProcessRequest(HttpContext context)
{
/* Your handler implementation */
}
}
To:
class YourHttpHandler : IHttpHandler
{
public bool IsReusable => true;
public void ProcessRequest(HttpContext context)
=> ProcessRequest(new HttpContextWrapper(context));
public virtual void ProcessRequest(HttpContextBase context)
{
/* Your handler implementation */
}
}
Your functionality needs to be moved from ProcessRequest(HttpContext context) to ProcessRequest(HttpContextBase context).
The ProcessRequest(HttpContextBase context) method can now be called in your tests with a mock object to verify the functionality within.
It's useful the create a helper class that can be used to quickly instantiate YourHttpHandler, send a mocked request, and get access to the response.
public class YourHttpHandlerTester : YourHttpHandler
{
public class Response
{
public HttpResponseBase HttpResponse { get; }
public string Body { get; }
public Response(HttpResponseBase httpResponse, string body)
{
HttpResponseBase = httpResponse;
Body = body;
}
}
public Response ProcessRequest(HttpRequestBase httpRequest)
{
var memoryStream = new MemoryStream();
var httpResponse = CreateHttpResponse(memoryStream);
var httpContext = CreateHttpContext(httpRequest, httpResponse);
base.ProcessRequest(httpContext);
var response = CreateResponse(httpResponse, memoryStream);
return response;
}
protected virtual HttpResponseBase CreateHttpResponse(MemoryStream memoryStream)
{
var httpResponseBaseMock = new Moq.Mock<HttpResponseBase>();
httpResponseBaseMock.Setup(x => x.OutputStream).Returns(memoryStream);
return httpResponseBaseMock.Object;
}
protected virtual HttpContextBase CreateHttpContext(HttpRequestBase httpRequest, HttpResponseBase httpResponse)
{
var httpContextBaseMock = new Moq.Mock<HttpContextBase>();
httpContextBaseMock.Setup(x => x.Request).Returns(httpRequest);
httpContextBaseMock.Setup(x => x.Response).Returns(httpResponse);
return httpContextBaseMock.Object;
}
protected virtual Response CreateResponse(HttpResponseBase httpResponse, MemoryStream memoryStream)
{
memoryStream.Position = 0;
var body = new StreamReader(memoryStream).ReadToEnd();
var response = new Response(httpResponse, body);
return response;
}
}
This class can be used to quickly create readable tests:
[Fact]
public void Test()
{
var httpHandler = new YourHttpHandlerTester();
var request = CreateHttpRequestFromString("test");
var response = testHandler.ProcessRequest(request);
Assert.NotEmpty(response.Body);
}
public HttpRequestBase CreateHttpRequestFromString(string body)
{
var httpRequestBaseMock = new Moq.Mock<HttpRequestBase>();
var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(body)))
httpRequestBaseMock.Setup(x => x.InputStream).Returns(stream);
return httpRequestBaseMock.Object;
}
YourHttpHandlerTester has plenty of virtual methods that can be overridden as necessary.
Likewise, the Response class can be improved so that it exposes methods from HttpResponseBase like the http status code, headers, and anything else you may want to check.
You can do INTEGRATION testing of the handler using the methods mentioned in the other answers, to do UNIT testing you will need to create some interfaces and extract the core functionality out of the handler, as well as create some mock objects.
You won't be able to unit test ALL parts of it because it relies upon outside resources (those you'll be mocking) - but that's fine, thats why we HAVE integration testing.
If you want to test the communication between your handlers and the Web UI then yes, integration testing is the way to go for that. In order to unit test your logic, could you not instead separate your business logic into other classes (I'd use a separate assembly for the business layer) and mock / unit test these classes instead outside of your presentation layer?
Once you have a structured (and unit tested) business layer that has been separated from the presentation layer your handlers can simply instantiate your concretes and invoke the provided methods. Once this is done, you can then move onto integration testing as your business logic will have been unit tested.

Resources