Verifying Mock method was called inside Task.Run - c#

How can I verify that a method was called on a mock when the method itself is called in a delegate passed to Task.Run? By time mock.Verify is called the Task still hasn't executed.
I have tried await Task.Delay just before mock.Verify but this seems to leave the test runner hanging.
The reason for using Task.Run is to offload the logic to prevent an attacker from being able to differentiate whether the email address exists in the system by the time to execute.
using System.Threading.Tasks;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace AsyncTesting
{
class MyController : Controller
{
public IEmailService EmailService { get; set; }
public MyController(IEmailService emailService)
{
EmailService = emailService;
}
public ViewResult BeginPasswordReset(string emailAddress)
{
BeginPasswordResetAsync(emailAddress);
return View();
}
private Task BeginPasswordResetAsync(string emailAddress)
{
return Task.Run(delegate
{
EmailService.Send(emailAddress);
});
}
}
internal interface IEmailService
{
void Send(string emailAddress);
}
internal class MyControllerTests
{
[TestMethod]
public void BeginPasswordReset_SendsEmail()
{
var mockEmailService = new Mock<IEmailService>();
var controller = new MyController(mockEmailService.Object);
const string emailAddress = "email#domain.com";
controller.BeginPasswordReset(emailAddress);
mockEmailService.Verify(es=>es.Send(emailAddress));
}
}
}

In your task you could set a ManualResetEvent (which our test code blocks on using something like:
Assert.IsTrue(yourEvent.WaitForOne(TimeSpan.FromSecond(<max time you want to wait>), "the event failed to run");
like this:
public void BeginPasswordReset_SendsEmail()
{
const string emailAddress = "email#domain.com";
ManualResetEvent sendCalled= new ManualResetEvent(false);
var mockEmailService = new Mock<IEmailService>();
mockEmailService.Setup(m => m.Send(emailAddress)).Callback(() =>
{
sendCalled.Set();
});
var controller = new MyController(mockEmailService.Object);
controller.BeginPasswordReset(emailAddress);
Assert.IsTrue(sendCalled.WaitOne(TimeSpan.FromSeconds(3)), "Send was never called");
mockEmailService.Verify(es => es.Send(emailAddress));
}

Some quick research it looks like it is possible with MSTest. e.g.
[TestMethod]
public async Task BeginPasswordResetAsync();
{
await BeginPasswordResetAsync("emailAddress");
mockEmailService.Verify...
}

Related

How to mock MassTransit Header values in unit test using NSubstitute

I'm trying to create a unit test that will test my MassTransit (RabbitMq) consumer. My consumer is expected a bus header key called UserName. I've simplified my consumer class as follows. I need to find a way to mock the bus header data otherwise the test will always raise an exception when it executes context.Headers.TryGetHeader("UserName", out object value)
I'm using the NSubstitute mocking library. So how do I mock the ConsumeContext<MyDataObject> type, and set a mock header value? I prefer a solution with NSubstitute
public class MyDataObjectCommand
{
public string MyProperty { get; set; }
}
// Consumer class
public class MyConsumer : IConsumer<MyDataObjectCommand>
{
private readonly IHubContext<MessageHub> _hubContext;
public MyConsumer(IHubContext<MessageHub> hubContext)
{
_hubContext = hubContext;
}
public async Task Consume(ConsumeContext<MyDataObjectCommand> context)
{
var myProperty = context.Message.MyProperty;
var userName = TryGetHeader(context, "UserName");
DoSomethingWith(_hubContext, myProperty, userName);
}
private string TryGetHeader(ConsumeContext<MyDataObjectCommand> context, string key, bool errorOnNull = true)
{
if (context.Headers.TryGetHeader(key, out object value))
{
return Convert.ToString(value);
}
if (errorOnNull)
{
throw new MyConsumerException(_reportName, $"{key} is not found", _hubContext);
}
return null;
}
}
// Unit Test (I'm using XUnit)
public class MyConsumerTests
{
private readonly IHubContext<MessageHub> _hubContext;
public MyConsumerTests()
{
_hubContext = Substitute.For<IHubContext<MessageHub>>();
}
[Fact]
public async Task ShouldConsume()
{
// arrange
var mockDataObject = new MyDataObjectCommand() { MyProperty = "x" };
var harness = new InMemoryTestHarness();
harness.Consumer(() => new MyConsumer(_hubContext));
// I need to mock header values on ConsumeContext<MyDataObjectCommand> object here
// but how do I do it using NSubstitute?
// context.Headers["UserName"] = "Bob"; ??
await harness.Start();
try
{
// act
await harness.InputQueueSendEndpoint.Send(mockDataObject);
// assert
Assert.True(await harness.Consumed.Any<MyDataObjectCommand>());
Assert.False(await harness.Consumed.Any<Fault<MyDataObjectCommand>>());
//Assert.Equal(context.Header["UserName"], "Bob"); How do I do the assertion??
}
finally
{
await harness.Stop();
}
}
}
You don’t mock header values when using MassTransit, you just have to set them when you’re sending the message using the test harness. There is absolutely zero need for a mocking framework.
await harness.InputQueueSendEndpoint.Send(mockDataObject,
context => context.Headers.Set(“UserName”, “Bob”));
The header will then be available on the ConsumeContext when the message is delivered to the consumer.

C# webapi async context issue

I got two console applications which calls my webapi the same time and I get back in the console application the follow response from my api:
A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.
So they call at the same time my webapi and then something inside the webapi cannot handle those 2 async calls so this error is returned.
I checked all my code on the webapi project and all methods are async and got await so I cannot see why I get this.
Here is the code of the webapi.
Controller:
public class FederationsController : ApiController
{
private readonly IFederationRepository _federationRepository;
public FederationsController(IFederationRepository federationRepository)
{
_federationRepository = federationRepository;
}
[HttpGet]
[Route("federations", Name = "GetFederations")]
public async Task<IHttpActionResult> GetFederations()
{
var federations = await _federationRepository.GetAllAsync();
return Ok(federations.ToModel());
}
}
Repository
public class FederationRepository : IFederationRepository, IDisposable
{
private Models.DataAccessLayer.CompetitionContext _db = new CompetitionContext();
#region IQueryable
private IQueryable<Models.Entities.Federation> FederationWithEntities()
{
return _db.Federations.Include(x => x.Clubs)
.Where(x => !x.DeletedAt.HasValue && x.Clubs.Any(y => !y.DeletedAt.HasValue));
}
#endregion IQueryable
public async Task<IEnumerable<Models.Entities.Federation>> GetAllAsync()
{
return await FederationWithEntities().ToListAsync();
}
}
Mapper
public static class FederationMapper
{
public static List<Federation> ToModel(this IEnumerable<Models.Entities.Federation> federations)
{
if (federations == null) return new List<Federation>();
return federations.Select(federation => federation.ToModel()).ToList();
}
public static Federation ToModel(this Models.Entities.Federation federation)
{
return new Federation()
{
Name = federation.Name,
FederationCode = federation.FederationCode,
CreatedAt = federation.CreatedAt,
UpdatedAt = federation.UpdatedAt
};
}
}
DbContext
public class CompetitionContext : DbContext
{
public CompetitionContext() : base("ContextName")
{
}
public DbSet<Federation> Federations { get; set; }
}
UnityConfig
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IFederationRepository, FederationRepository>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Thank you for all the advices/help.
In your repository you are creating a single CompetitionContext and reusing it. I'm assuming that IoC setup is registring the repository as some kind of single instance, so the same repository is getting used every time. If that's the case you should create a new CompetitionContext for each method call.
Also, probably should make sure it's closed with a using statement.
I'm also not clear from your code snippets why you are returning an IQueryable from that FederationWithEntities, method, do you have other things that are using it?
Anyway, I'd probably change that GetAllMethod to be something like this:
public async Task<IEnumerable<Models.Entities.Federation>> GetAllAsync()
{
using (Models.DataAccessLayer.CompetitionContext _db = new CompetitionContext())
{
return _db.Federations.Include(x => x.Clubs)
.Where(x => !x.DeletedAt.HasValue && x.Clubs.Any(y => !y.DeletedAt.HasValue))
.ToListAsync();
}
}

Does Visual Studio extension packages support asyncronous operations

I am creating a custom visual studio extension. In its initialization code I use async-await to make async WebRequest to a remote endpoint.
The problem is that the moment I call await statement, the execution of my custom extension initialization halts and never gets back to it. I suspect VS extensions initialization code is somehow special when it comes to async programming. If anyone could point me to an explanation of why this is happening, I'd greatly appreciate it.
There is a new Package called AsyncPackage that allows async loading of your package. It has an AsyncInitialize. Taken from MSDN:
You need to add a reference to Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime for this to work
using System;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using System.Threading;
using System.Runtime.CompilerServices;
using System.IO;
namespace asyncpackagetest
{
[ProvideService((typeof(STextWriterService)), IsAsyncQueryable = true)]
[ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string, PackageAutoLoadFlags.BackgroundLoad)]
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[Guid(VSPackage1.PackageGuidString)]
public sealed class VSPackage1 : AsyncPackage
{
public const string PackageGuidString = "3dc186f8-2146-4d89-ac33-e216b3ead526";
public VSPackage1()
{
}
protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
this.AddService(typeof(STextWriterService), CreateService);
await base.InitializeAsync(cancellationToken, progress);
ITextWriterService textService = await this.GetServiceAsync(typeof(STextWriterService)) as ITextWriterService;
await textService.WriteLineAsync(#"c:\windows\temp\async_service.txt", "this is a test");
}
public async System.Threading.Tasks.Task<object> CreateService(IAsyncServiceContainer container, CancellationToken cancellationToken, Type serviceType)
{
STextWriterService service = null;
await System.Threading.Tasks.Task.Run(() => {
service = new TextWriterService(this);
});
return service;
}
public class TextWriterService : STextWriterService, ITextWriterService
{
private Microsoft.VisualStudio.Shell.IAsyncServiceProvider serviceProvider;
public TextWriterService(Microsoft.VisualStudio.Shell.IAsyncServiceProvider provider)
{
serviceProvider = provider;
}
public async System.Threading.Tasks.Task WriteLineAsync(string path, string line)
{
StreamWriter writer = new StreamWriter(path);
await writer.WriteLineAsync(line);
writer.Close();
}
public TaskAwaiter GetAwaiter()
{
return new TaskAwaiter();
}
}
public interface STextWriterService
{
}
public interface ITextWriterService
{
System.Threading.Tasks.Task WriteLineAsync(string path, string line);
TaskAwaiter GetAwaiter();
}
}
}

MahApps TDD ShowProgressDialog

Sorry for two posts.
I have the following code which I stole from the MahApps example. This has the updated code example
using System.Threading.Tasks;
using MahApps.Metro.Controls.Dialogs;
namespace MyNameSpace {
public class MyClass {
public MyClass(IDialogCoordinator dialogCoordinator,IMyService myservice){
_dialogCoordinator =dialogCoordinator;
_mySerice =myservice;
}
public async Task<bool> MethodUnderTest() {
var controller = await _dialogCoordinator.ShowProgressAsync(this,"Please wait...", "We are baking some cupcakes!");
controller.SetIndeterminate();
await Task.Delay(5000);
controller.SetCancelable(true);
if (!controller.IsCanceled) {
controller.SetProgress(0.50);
controller.SetMessage("Half way there");
await Task.Factory.StartNew(()=> {
_myservice.MyMethodIWannaTest();
});
}
await controller.CloseAsync();
if (controller.IsCanceled) {
await dialogCoordinator.ShowMessageAsync(this,"No cupcakes!", "You stopped baking!");
return false;
} else {
await dialogCoordinator.ShowMessageAsync(this,"Cupcakes!", "Your cupcakes are finished! Enjoy!");
return true;
}
}
private IDialogCoordinator _dialogCoordinator;
private IMyService _myService;
}
}
How do I test to verify that MyMethodIWannaTest is called (Since I can't Moq ShowProgressAync???
using Moq;
using MahApps.Metro.Controls.Dialogs;
[TestMethod]
public void MethodUnderTestCallsMyServiceMyMethodIWannaTest() {
var _mockDialogCoordinator = new Mock<IDialogCoordinator>();
var _mockMyService = new Mock<IMyService>();
// Arrange
var viewModel = new MyClass(_mockDialogCoordinator.Object,_mockMyService.Object);
//NOT SURE WHAT TO DO TO MAKE IT WORK?
_mockDialogCoordinator.Setup(
d => d.ShowProgressAsync(viewModel, "Please wait...", "We are creating your package!", true, null))
.Returns(Task.Factory.StartNew(Activator.CreateInstance<ProgressDialogController>)); //Still does not work always returns null :(
// Act
viewModel.MethodUnderTest();
// Assert
_mockMyService.Verify(ms => ms.MyMethodIWannaTest());
}
Not sure what I am doing wrong, any help appreciated!!

ASP.NET MVC WebAPI create ViewModel from async tasks

I write web application using ASP.NET MVC WebAPI and I want to transform current synchronous code to asynchronous for optimization. Problem is that I fill ViewModel with multiple objects taken from repository. These calls from repository should be async.
Let's asume I have signature for repository calls respecting this interface
public interface ICompanyRepository
{
IEnumerable<Company> GetCompanies();
IEnumerable<Address> GetAddresses();
}
ViewModels definition
public class CompaniesFullViewModel
{
public IEnumerable<Company> Companies { get; set; }
public IEnumerable<Address> Addresses { get; set; }
}
And controller:
public class CompanyController
{
public readonly ICompanyRepository Repository { get; private set; }
public CompanyController(IRepository repository)
{
Repository = repository;
}
[ResponseType(typeof(CompaniesFullViewModel))]
public HttpResponseMessage Get()
{
var companies = Repository.GetCompanies();
var addresses = Repository.GetAddresses();
HttpStatusCode statusCode = companies.Any()
? HttpStatusCode.OK
: HttpStatusCode.PartialContent;
return
Request.CreateResponse(
statusCode,
new CompaniesFullViewModel
{
Companies = companies,
Addresses = addresses
});
}
}
Furthermore I have tests implemented to the controller:
[TestClass]
public sealed class CompanyTestController : BaseTestController
{
#region Fields
private static Mock<ICompanyRepository> _repositoryMock;
private static CompanyController _controller;
#endregion
[ClassInitialize]
public static void Initialize(TestContext testContext)
{
// Mock repository
_repositoryMock = new Mock<ICompanyRepository>();
DependencyResolver.Default.Container.RegisterInstance(_repositoryMock.Object);
// Create controller
_controller =
DependencyResolver.Default.Container.Resolve<CompanyController>();
// Init request
_controller.Request = new HttpRequestMessage();
_controller.Request.SetConfiguration(new HttpConfiguration());
}
[ClassCleanup]
public static void Cleanup()
{
_controller.Dispose();
}
[TestMethod]
public void Get_ActionExecutes_ReturnsEmptyCompaniesViewModel()
{
var companies = new List<Company>();
var addresses = new List<Address>();
// Setup fake method
_repositoryMock
.Setup(c => c.GetCompanies())
.Returns(companies);
_repositoryMock
.Setup(c => c.GetAddresses())
.Returns(addresses);
// Execute action
var response = _controller.Get();
// Check the response
Assert.AreEqual(HttpStatusCode.PartialContent, response.StatusCode);
}
}
How can I convert the controller to async, if the repository is async and the signature looks like this:
public interface ICompanyRepository
{
Task<IEnumerable<Company>> GetCompaniesAsync();
Task<IEnumerable<Address>> GetAddressesAsync();
}
What you need to do is change the Controller action to be async as well, and change the return type to Task<>. You can then await your asynchronous repository calls:
[ResponseType(typeof(CompaniesFullViewModel))]
public async Task<HttpResponseMessage> Get() // async keyword.
{
var companies = await Repository.GetCompaniesAsync(); // await
var addresses = await Repository.GetAddressesAsync(); // await
HttpStatusCode statusCode = companies.Any()
? HttpStatusCode.OK
: HttpStatusCode.PartialContent;
return
Request.CreateResponse(
statusCode,
new CompaniesFullViewModel
{
Companies = companies,
Addresses = addresses
});
}
By convention, you can also change the name of the controller action to end in Async as well, although if you are using RESTful conventions and / or Routing attributes, the actual name of the controller action isn't really important.
Testing
I use XUnit and NUnit, but it seems MSTest also supports testing of asynchronous methods, and Moq also provides Async versions of the setups:
[Test]
public async Task Get_ActionExecutes_ReturnsEmptyCompaniesViewModel() // async Task
{
var companies = new List<Company>();
var addresses = new List<Address>();
// Setup fake method
_repositoryMock
.Setup(c => c.GetCompaniesAsync())
.ReturnsAsync(companies); // Async
_repositoryMock
.Setup(c => c.GetAddressesAsync())
.ReturnsAsync(addresses); // Async
// Execute action
var response = await _controller.Get(); // Await
// Check the response
Assert.AreEqual(HttpStatusCode.PartialContent, response.StatusCode);
_repositoryMock.Verify(m => m.GetAddressesAsync(), Times.Once);
_repositoryMock.Verify(m => m.GetCompaniesAsync(), Times.Once);
}
As an aside, it seems you are using Setter Dependency injection. An alternative is to use Constructor injection, which has the benefit of ensuring that the class is always in a valid state (i.e. there is no transient state while it is waiting for the dependencies to be set). This also allows the dependencies (your repository in this case) to be made readonly.

Categories

Resources